import m3 from './m3.js'
import webglUtils from './webgl-utils.js'
import waterColor from './waterColor'

const Chart = function () {
  let _gl
  let _textCtx
  let _config
  let _container
  let _textcontainer

  let containerWidth = null
  let containerHeight = null

  // 着色器相关变量
  let _pointShaderProgram
  let _pointPositionAttributeLocation
  let _pointSizeAttributeLocation
  let _pointFragColor
  let _pointMatrixLocation

  let _lineShaderProgram
  let _linePositionAttributeLocation
  let _lineFragColor
  let _linematrixLocation

  let _lineShaderProgramUseVaringColor
  let _linePositionAttributeLocationUseVaringColor
  let _lineColorAttributeLocationUseVaringColor
  let _linematrixLocationUseVaringColor

  let _imageProgram
  let _imagePositionAttributeLocation
  let _imageTexcoordAttributeLocation
  let _imageMatrixLocation
  let _imgTexure

  let _buffer = null
  let _buffer2 = null

  let _imageList = []

  let _axisMatrix
  // let _linesMatrix

  // 鼠标是否按下
  let _isMouseDown = false
  // 记录鼠标点击开始位置
  let _mouseDownStart
  let _lastMousePosition = null
  let _isClickMarkLine = false
  let _clickedMarkLine = null
  let _clickedMarkLineSeries = null

  let _isClickMeasureZone = false
  let _clickedMeasureZone = null
  let _clickedMeasureZoneSeries = null

  let _isClickToDragMeasureZone = false
  let _clickedToDragMeasureZone = null

  let _onclickTimer = null
  let _isClickYaxisPadding = false
  let _isClickXaxisPadding = false
  let _clickedYaxisSeries = null
  let _clickedXaxisSeries = null
  let _mouseMovePre = null
  let _markIdIdx = 1

  /**
   * 瀑布图每张图片最大宽度（如果数据点数超过这个宽度，则拆分成多张图片）
   */
  const _maxPointNum = 8000

  const _compassConfig = {
    // 罗盘刻度的偏移角度
    compassScaleRotation: null,
    // 罗盘指针初始偏移角度
    compassPointOldRotation: null,
    // 罗盘指针当前偏移角度
    compassPointRotation: null,
    // 罗盘测量事件监听器
    compassMeasureListener: null,
    // 是否点击了罗盘指针
    isClickCompassPoint: false,
    // 罗盘matrix
    compassMatrix: null,
    // 罗盘指针matrix
    compassPointMatrix: null,
    // 之前的角度
    preJiaotdu: null,
    // 鼠标拖拽总角度变化差值
    totalJiaoDuChange: null,
    // 鼠标拖拽的扇形的数组
    sectorPoints: [],
    comapssPoints: [],
    comapssPointsSizes: [],
    // 需要显示的点的数组
    comapssShowPoints: [],
    // 需要显示的点的大小数组
    compassShowPointSizes: [],
    // 点的大小
    pointSize: 5,
    // 显示点开始角度和显示点的结束角度间的差值
    pointShowJiaoDuChange: null,
    // 置信度
    confidence: null,
    // 车位角度
    compassCarPositionRotation: null,
    // 车位matrix
    compassCarPositionMatrix: null,
    backgroundColor: null,
    wordColor: null
  }

  const _Series = []

  // 节流函数
  function throttle (func, timeout) {
    let timer
    return function () {
      if (timer) {
        return
      }
      timer = setTimeout(() => {
        timer = null
        func.apply(this, Array.from(arguments))
      }, timeout)
    }
  }

  // 准备WebGL上下文
  function _prepareContext () {
    const DPR = window.devicePixelRatio
    // 使用Canvas
    const div = document.querySelector('#' + _config.container)

    containerWidth = div.clientWidth
    containerHeight = div.clientHeight
    const webGlCanvasNode = document.createElement('canvas')
    div.appendChild(webGlCanvasNode)
    const textCanvasNode = document.createElement('canvas')
    div.appendChild(textCanvasNode)

    webGlCanvasNode.style.width = '100%'
    webGlCanvasNode.style.height = '100%'
    webGlCanvasNode.width = div.clientWidth
    webGlCanvasNode.height = div.clientHeight
    _container = webGlCanvasNode
    _textcontainer = textCanvasNode
    div.style.position = 'relative'
    textCanvasNode.style.backgroundColor = 'transparent'
    textCanvasNode.style.position = 'absolute'
    textCanvasNode.style.left = '0px'
    textCanvasNode.style.top = '0px'
    textCanvasNode.style.zIndex = '2'
    textCanvasNode.style.width = '100%'
    textCanvasNode.style.height = '100%'
    textCanvasNode.width = div.clientWidth
    textCanvasNode.height = div.clientHeight
    _gl = _container.getContext('webgl', {
      preserveDrawingBuffer: true,
      antialias: true,
      antialiasSamples: 8
    })

    _textCtx = _textcontainer.getContext('2d')
    // 清空二维画布
    _textCtx.clearRect(0, 0, _container.width, _container.height)
    if (!_gl) {
      // console.log('无法使用WebGL！')
    } else {
      // //console.log(_gl)
    }
  }

  function _initGl () {
    // 环境上下文准备
    _prepareContext()

    // 编译
    const pointVertexShader = _setupShader(
      _gl,
      _gl.VERTEX_SHADER,
      pointVertexShaderSource
    )
    const pointFragmentShader = _setupShader(
      _gl,
      _gl.FRAGMENT_SHADER,
      pointFragmentShaderSource
    )

    // 链接
    _pointShaderProgram = linkShader(
      _gl,
      pointVertexShader,
      pointFragmentShader
    )
    _pointPositionAttributeLocation = _gl.getAttribLocation(
      _pointShaderProgram,
      'a_position'
    )
    _pointSizeAttributeLocation = _gl.getAttribLocation(
      _pointShaderProgram,
      'a_PointSize'
    )
    _pointMatrixLocation = _gl.getUniformLocation(
      _pointShaderProgram,
      'matrix'
    )

    // 获取u_FragColor变量的存储位置
    _pointFragColor = _gl.getUniformLocation(
      _pointShaderProgram,
      'u_FragColor'
    )

    // 编译
    const lineVertexShader = _setupShader(
      _gl,
      _gl.VERTEX_SHADER,
      lineVertexShaderSource
    )
    const lineFragmentShader = _setupShader(
      _gl,
      _gl.FRAGMENT_SHADER,
      lineFragmentShaderSource
    )

    // 链接
    _lineShaderProgram = linkShader(_gl, lineVertexShader, lineFragmentShader)
    _linePositionAttributeLocation = _gl.getAttribLocation(
      _lineShaderProgram,
      'a_position'
    )

    // 获取u_FragColor,matrix变量的存储位置
    _lineFragColor = _gl.getUniformLocation(_lineShaderProgram, 'u_FragColor')
    _linematrixLocation = _gl.getUniformLocation(_lineShaderProgram, 'matrix')

    // 编译
    const imageVertexShader = _setupShader(
      _gl,
      _gl.VERTEX_SHADER,
      imgVertexShaderSource
    )
    const imageFragmentShader = _setupShader(
      _gl,
      _gl.FRAGMENT_SHADER,
      imgFragmentShaderSource
    )

    // 链接
    _imageProgram = linkShader(_gl, imageVertexShader, imageFragmentShader)
    _imagePositionAttributeLocation = _gl.getAttribLocation(
      _imageProgram,
      'a_position'
    )
    _imageTexcoordAttributeLocation = _gl.getAttribLocation(
      _imageProgram,
      'a_texCoord'
    )

    // u_matrix
    _imageMatrixLocation = _gl.getUniformLocation(_imageProgram, 'u_matrix')

    // 编译
    const lineVertexShaderUseVaringColor = _setupShader(
      _gl,
      _gl.VERTEX_SHADER,
      lineVertexShaderSourceUseVaringColor
    )
    const lineFragmentShaderUseVaringColor = _setupShader(
      _gl,
      _gl.FRAGMENT_SHADER,
      lineFragmentShaderSourceUseVaringColor
    )

    // 链接
    _lineShaderProgramUseVaringColor = linkShader(
      _gl,
      lineVertexShaderUseVaringColor,
      lineFragmentShaderUseVaringColor
    )

    _linePositionAttributeLocationUseVaringColor = _gl.getAttribLocation(
      _lineShaderProgramUseVaringColor,
      'a_position'
    )
    _lineColorAttributeLocationUseVaringColor = _gl.getAttribLocation(
      _lineShaderProgramUseVaringColor,
      'a_color'
    )

    // 获取matrix变量的存储位置
    _linematrixLocationUseVaringColor = _gl.getUniformLocation(
      _lineShaderProgramUseVaringColor,
      'matrix'
    )
  }

  /**
   * 编译着色器
   * @param {*} gl
   * @param {*} type
   * @param {*} source
   * @returns
   */
  function _setupShader (gl, type, source) {
    const shader = gl.createShader(type)
    gl.shaderSource(shader, source)
    gl.compileShader(shader)

    const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS)
    if (success) {
      return shader
    }

    // console.log(gl.getShaderInfoLog(shader))
    gl.deleteShader(shader)
  }
  /**
   *  链接着色器
   * @param {*} gl
   * @param {*} vertexShader
   * @param {*} fragmentShader
   * @returns
   */
  function linkShader (gl, vertexShader, fragmentShader) {
    const program = gl.createProgram()
    gl.attachShader(program, vertexShader)
    gl.attachShader(program, fragmentShader)
    gl.linkProgram(program)
    const success = gl.getProgramParameter(program, gl.LINK_STATUS)
    if (success) {
      return program
    }

    // console.log(gl.getProgramInfoLog(program))
    gl.deleteProgram(program)
  }
  /**
   * 创建缓冲区，并填入顶点数据
   * @param {*} data
   */
  function _createBuffer (data) {
    if (!_buffer) {
      _buffer = _gl.createBuffer()
    }
    _gl.bindBuffer(_gl.ARRAY_BUFFER, _buffer)
    _gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(data), _gl.STATIC_DRAW)
    return _buffer
  }

  function _createBuffer2 (data) {
    if (!_buffer2) {
      _buffer2 = _gl.createBuffer()
    }
    _gl.bindBuffer(_gl.ARRAY_BUFFER, _buffer2)
    _gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(data), _gl.STATIC_DRAW)
    return _buffer2
  }

  /**
   * 绘制线段组
   * @param {*} points 点数据
   * @param {*} matirx 变换矩阵
   * @param {*} color 颜色
   */
  function _drawLineGroup (points, matirx, color) {
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 1)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matirx)
    _gl.drawArrays(_gl.LINES, 0, points.length / 2)
  }

  /**
   * 绘制线段组
   * @param {*} points 点数据
   * @param {*} matirx 变换矩阵
   * @param {*} color 颜色
   */
  function _drawLineGroupWithLineStrip (points, matirx, color) {
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 1)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matirx)
    _gl.drawArrays(_gl.LINE_STRIP, 0, points.length / 2)
  }

  /**
   * 绘制线段组,每个点单独设置颜色
   * @param {*} points 点数据
   * @param {*} matirx 变换矩阵
   * @param {*} color 颜色
   */
  function _drawLineGroupWithVaringColor (points, matirx, colors) {
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgramUseVaringColor)
    _gl.enableVertexAttribArray(_linePositionAttributeLocationUseVaringColor)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocationUseVaringColor,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _createBuffer(colors)
    _gl.enableVertexAttribArray(_lineColorAttributeLocationUseVaringColor)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _lineColorAttributeLocationUseVaringColor,
      4,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocationUseVaringColor, false, matirx)
    _gl.drawArrays(_gl.LINES, 0, points.length / 2)
  }

  /**
   * 绘制沿x轴方向的有宽度的直线
   * @param {*} x1
   * @param {*} y1
   * @param {*} x2
   * @param {*} y2
   * @param {*} width
   * @param {*} matrix
   * @param {*} color
   */
  function _drawXLineWithWidth (x1, y1, x2, y2, width, matrix, color) {
    const points = [
      x1,
      y1 + width / 2,
      x1,
      y2 - width / 2,
      x2,
      y1 + width / 2,
      x1,
      y2 - width / 2,
      x2,
      y1 + width / 2,
      x2,
      y2 - width / 2
    ]
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 1)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.TRIANGLES, 0, points.length / 2)
  }

  /**
   * 绘制沿y轴方向的有宽度的直线
   * @param {*} x1
   * @param {*} y1
   * @param {*} x2
   * @param {*} y2
   * @param {*} width
   * @param {*} matrix
   * @param {*} color
   */
  function _drawYLineWithWidth (x1, y1, x2, y2, width, matrix, color) {
    const points = [
      x1 + width / 2,
      y1,
      x1 + width / 2,
      y2,
      x2 - width / 2,
      y1,
      x1 + width / 2,
      y2,
      x2 - width / 2,
      y1,
      x2 - width / 2,
      y2
    ]
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 1)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.TRIANGLES, 0, points.length / 2)
  }
  /**
   * 绘制透明矩形
   * @param {*} points 矩形6个点的坐标
   * @param {*} matrix
   * @param {*} color
   */
  function _drawTransparentRect (points, matrix, color) {
    _createBuffer(points)
    _gl.enable(_gl.BLEND)
    // 指定混合函数
    _gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 0.2)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.TRIANGLES, 0, points.length / 2)
  }

  /**
   * 绘制矩形 每个点单独设置颜色
   * @param {*} points 矩形点数组
   * @param {*} matrix 变换矩阵
   * @param {*} colors 颜色数组(vec4)
   */
  function _drawTranglesWithVaringColor (points, matrix, colors) {
    _createBuffer(points)
    _gl.enable(_gl.BLEND)
    // 指定混合函数
    _gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA)
    _gl.useProgram(_lineShaderProgramUseVaringColor)
    _gl.enableVertexAttribArray(_linePositionAttributeLocationUseVaringColor)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocationUseVaringColor,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _createBuffer2(colors)
    _gl.enableVertexAttribArray(_lineColorAttributeLocationUseVaringColor)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _lineColorAttributeLocationUseVaringColor,
      4,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocationUseVaringColor, false, matrix)

    _gl.drawArrays(_gl.TRIANGLES, 0, points.length / 2)
  }

  /**
   * 绘制透明图形
   * @param {*} points 点的坐标
   * @param {*} matrix
   * @param {*} color
   */
  function _drawTransparentTrangleFan (points, matrix, color) {
    _createBuffer(points)
    _gl.enable(_gl.BLEND)
    // 指定混合函数
    _gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    if (color.a) {
      // 设置颜色
      _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, color.a)
    } else {
      // 设置颜色
      _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 0.2)
    }

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.TRIANGLE_FAN, 0, points.length / 2)
  }

  /**
   * 绘制三角形
   * @param {*} points 三角形点的坐标
   * @param {*} matrix
   * @param {*} color
   */
  function _drawTrangles (points, matrix, color) {
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 1)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.TRIANGLES, 0, points.length / 2)
  }

  /**
   * 绘制透明的三角形
   * @param {*} points 三角形点的坐标
   * @param {*} matrix
   * @param {*} color
   */
  function _drawTransparentTrangles (points, matrix, color) {
    _createBuffer(points)
    _gl.enable(_gl.BLEND)
    // 指定混合函数
    _gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, color.a)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.TRIANGLES, 0, points.length / 2)
  }

  /**
   * 绘制圆圈
   * @param {*} vertexData 圆圈上的点
   */
  function _drawHollowCircleWithPoints (points, matrix, color) {
    _createBuffer(points)
    _gl.useProgram(_lineShaderProgram)
    _gl.enableVertexAttribArray(_linePositionAttributeLocation)
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _linePositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    // 设置颜色
    _gl.uniform4f(_lineFragColor, color.r, color.g, color.b, 1)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_linematrixLocation, false, matrix)

    _gl.drawArrays(_gl.LINE_LOOP, 0, points.length / 2)
  }

  /**
   * 绘制多个有宽度的点
   */
  function _drawWidthPoints (points, matrix, size, color) {
    // 准备输入数据
    _createBuffer(points)
    const sizeData = size
    // 加载着色器，准备读取缓冲区的数据
    _gl.useProgram(_pointShaderProgram)
    _gl.enableVertexAttribArray(_pointPositionAttributeLocation)
    // gl.vertexAttribPointer(position_attribute_location, size, type, normalize, stride, offset);
    // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
    // type=gl_FLOAT表示使用的是32为浮点类型的数据。
    // normalize=false表示不需要归一化数据。
    // offset=0表示从缓冲区的开始位置读取数据。
    _gl.vertexAttribPointer(
      _pointPositionAttributeLocation,
      2,
      _gl.FLOAT,
      false,
      0,
      0
    )

    _gl.uniform4f(_pointFragColor, color.r, color.g, color.b, 1)

    _createBuffer(sizeData)
    _gl.vertexAttribPointer(
      _pointSizeAttributeLocation,
      1,
      _gl.FLOAT,
      false,
      0,
      0
    )
    _gl.enableVertexAttribArray(_pointSizeAttributeLocation)

    // 设置变换矩阵
    _gl.uniformMatrix3fv(_pointMatrixLocation, false, matrix)

    _gl.drawArrays(_gl.POINTS, 0, points.length / 2)
  }

  // --------------------------------------------------------------------
  // 顶点着色器和片原着色器代码

  // 绘制点的顶点着色器代码
  const pointVertexShaderSource = `
    attribute vec2 a_position;
    attribute float a_PointSize;
    uniform mat3 matrix;
    void main() {
        gl_PointSize= a_PointSize;
        gl_Position = vec4(matrix  * vec3(a_position, 1), 1);
    }
  `
  // 绘制点的片原着色器代码
  const pointFragmentShaderSource = `
      precision mediump float;
      uniform vec4 u_FragColor;
      void main() {
          float d = distance(gl_PointCoord,vec2(0.5,0.5));
          if(d < 0.5){
            gl_FragColor = u_FragColor;
          }else{
              discard;
          }
      }
  `

  // 绘制线的顶点着色器代码
  const lineVertexShaderSource = `
    attribute vec2 a_position;
    uniform mat3 matrix;
    void main() {
        gl_PointSize=100.0;
        gl_Position = vec4((matrix  * vec3(a_position, 1)).xy, 0, 1);
    }
  `
  // 绘制线的片原着色器代码
  const lineFragmentShaderSource = `
      precision mediump float;
      uniform vec4 u_FragColor;
      void main() {
        gl_FragColor = u_FragColor;
      }
  `
  // 绘制线的顶点着色器代码(每个点的颜色单独传入 费内存)
  const lineVertexShaderSourceUseVaringColor = `
    attribute vec2 a_position;
    attribute vec4 a_color;
    uniform mat3 matrix;
    varying vec4 v_color;
    void main() {
        gl_PointSize=100.0;
        gl_Position = vec4((matrix  * vec3(a_position, 1)).xy, 0, 1);
        v_color = a_color;
    }
  `
  // 绘制线的片原着色器代码()
  const lineFragmentShaderSourceUseVaringColor = `
      precision mediump float;
      varying vec4 v_color;
      void main() {
        gl_FragColor = v_color;
      }
  `

  // 绘制图像的顶点着色器代码
  const imgVertexShaderSource = `
    attribute vec2 a_position;
    attribute vec2 a_texCoord;

    uniform mat3 u_matrix;
    
    varying vec2 v_texCoord;
    
    void main() {
      gl_Position = vec4(u_matrix * vec3(a_position,1), 1);
    
      // pass the texCoord to the fragment shader
      // The GPU will interpolate this value between points.
      v_texCoord = a_texCoord;
    }
  `
  const imgFragmentShaderSource = `
    precision mediump float;

    // our texture
    uniform sampler2D u_image;

    // the texCoords passed in from the vertex shader.
    varying vec2 v_texCoord;

    void main() {
      gl_FragColor = texture2D(u_image, v_texCoord);
    }
  `
  // -------------------------------------------------------------------------------
  /**
   * 全部涂黑
   */
  function _clear () {
    _gl.clearColor(
      _config.background.r,
      _config.background.g,
      _config.background.b,
      1
    )
    _gl.clear(_gl.COLOR_BUFFER_BIT)
    // 清空二维画布
    _textCtx.clearRect(0, 0, _container.width, _container.height)
  }
  /**
   * 刷新当前图表
   */
  function _refresh () {
    // 检测图表大小是否改变
    if (
      containerHeight != _container.clientHeight ||
      containerWidth != _container.clientWidth
    ) {
      const div = document.querySelector('#' + _config.container)
      _container.width = div.clientWidth
      _container.height = div.clientHeight
      _textcontainer.width = div.clientWidth
      _textcontainer.height = div.clientHeight
      _textCtx.width = div.clientWidth
      _textCtx.height = div.clientHeight
      containerWidth = div.clientWidth
      containerHeight = div.clientHeight
      _clearCaculatedData()
      // 清空计算矩阵
      _axisMatrix = null
      _Series.forEach((series) => {
        series._linesMatrix = null
        // 清空axis标记  的文字缓存
        series.xAxis.points = []
        series.yAxis.points = []
      })
    }
    // 清空所有区域
    _clear()
    if (_config.type === 'compass') {
      _drawCompassCircle()
      _drawCarPosition()
      _drawCompassPointer()
      _drawCompassPoints()
      _drawMouseStrap()
    } else {
      // 在axis区域填充颜色
      _fillAxisArea()
      // 绘制图表x轴y轴
      _drawSeriesAxis()
      if (_config.type === 'pubu') {
        _drawImage2D()
        _drawRectMarkZone()
      }
      _drawSeriesMouseStrapRect()
      _drawXMarkZones()
      _drawMarkLines()
      _drawMouseClickMarkPoints()
      if (_config.type === 'line') {
        // 绘制线条
        _drawSeriesLine()
      }
      if (_config.type === 'line') {
        _drawMeasure()
      }
      if (_config.type === 'pubu') {
        _drawTimeMeasure()
        _drawWaterColors()
      }
    }
  }

  /**
   * 绘制罗盘图的圆圈
   */
  function _drawCompassCircle () {
    if (!_compassConfig.compassMatrix) {
      // 根据分辨率直接生成矩阵
      let projectionMatrix = m3.projection(
        _gl.canvas.clientWidth,
        _gl.canvas.clientHeight
      )
      // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
      const translationMatrix = m3.translation(0, _gl.canvas.clientHeight)
      projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
      // scaling 绕原点翻转(-1 ~ 1)
      projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
      projectionMatrix = m3.multiply(
        projectionMatrix,
        m3.translation(_gl.canvas.clientWidth / 2, _gl.canvas.clientHeight / 2)
      )
      // _axisMatrix = projectionMatrix
      if (_compassConfig.compassScaleRotation) {
        projectionMatrix = m3.multiply(
          projectionMatrix,
          m3.rotation(_compassConfig.compassScaleRotation)
        )
      }
      _compassConfig.compassMatrix = projectionMatrix
    }

    const banjing = _container.clientHeight / 2 - 5
    const N = 4000
    const circlePoints = []
    // var sizeData = [pointSize, pointSize]

    // for (var i = 0; i <= N; i++) {
    //   let theta = i * 2 * Math.PI / N
    //   let x1 = 0 + banjing * Math.sin(theta)
    //   let y1 = 0 + banjing * Math.cos(theta)
    //   circlePoints.push(x1, y1)
    //   // sizeData.push(pointSize)
    // }
    // _drawHollowCircleWithPoints(circlePoints, _compassConfig.compassMatrix, {r: 1, g: 1, b: 1})

    //
    const circlePoints2 = []
    for (let j = 0; j <= 60; j++) {
      const theta = (j * 2 * Math.PI) / 60
      const x1 = 0 + banjing * Math.sin(theta)
      const y1 = 0 + banjing * Math.cos(theta)
      const x2 = 0 + (banjing - 5) * Math.sin(theta)
      const y2 = 0 + (banjing - 5) * Math.cos(theta)
      circlePoints2.push(x1)
      circlePoints2.push(y1)
      circlePoints2.push(x2)
      circlePoints2.push(y2)
    }
    _drawLineGroup(
      circlePoints2,
      _compassConfig.compassMatrix,
      _compassConfig.wordColor
    )

    // 绘制罗盘上的文字
    // 绘制中心的方位和置信度
    _textCtx.fillStyle =
      'rgb(' +
      _compassConfig.wordColor.r * 255 +
      ',' +
      _compassConfig.wordColor.g * 255 +
      ',' +
      _compassConfig.wordColor.b * 255 +
      ')'
    _textCtx.font = '20px sans-serif'
    if (_compassConfig.compassPointRotation != null) {
      const direction = (
        (_compassConfig.compassPointRotation * 180) /
        Math.PI
      ).toFixed(3)
      const str = direction + '°'
      _textCtx.fillText(
        str,
        _container.clientWidth / 2 - _textCtx.measureText(str).width - 5,
        _container.clientHeight / 2
      )
    }
    if (_compassConfig.confidence != null) {
      const str = _compassConfig.confidence
      _textCtx.fillText(
        str,
        _container.clientWidth / 2 + 5,
        _container.clientHeight / 2
      )
    }

    for (let i = 0; i < 12; i++) {
      let rotation = i * 30 * ((2 * Math.PI) / 360)
      if (_compassConfig.compassScaleRotation) {
        rotation += _compassConfig.compassScaleRotation
      }
      let str = i * 30 + ''
      if (i === 0) {
        str = 'N'
      }
      if (i === 3) {
        str = 'E'
      }
      if (i === 6) {
        str = 'S'
      }
      if (i === 9) {
        str = 'W'
      }
      const banjing = _container.clientWidth / 2 - 20
      const x =
        Math.sin(rotation) * banjing +
        _container.clientHeight / 2 -
        _textCtx.measureText(str).width / 2
      const y =
        _container.clientHeight -
        (Math.cos(rotation) * banjing + _container.clientHeight / 2) +
        5

      _textCtx.font = '10px sans-serif'
      _textCtx.fillText(str, x, y)

      // 绘制罗盘外层彩色圈圈
      const colorsTmp = waterColor.dirColors()
      const colors = []
      for (let i = 0; i < colorsTmp.length; i++) {
        colors.push(colorsTmp[colorsTmp.length - 1 - i])
      }
      const num = 240
      const colorBanjing1 = _container.clientHeight / 2 - 5
      const colorBanjing2 = _container.clientHeight / 2
      const colorCirclePoints = []
      const colorCirclePointsColors = []
      let preX1
      let preY1
      let preX2
      let preY2
      for (let i = 0; i <= num; i++) {
        const theta = (i * 2 * Math.PI) / num
        // 内层点坐标
        const x1 = 0 + colorBanjing1 * Math.sin(theta)
        const y1 = 0 + colorBanjing1 * Math.cos(theta)
        // 外层点坐标
        const x2 = 0 + colorBanjing2 * Math.sin(theta)
        const y2 = 0 + colorBanjing2 * Math.cos(theta)
        if (i > 0) {
          colorCirclePoints.push(preX1)
          colorCirclePoints.push(preY1)
          colorCirclePoints.push(preX2)
          colorCirclePoints.push(preY2)
          colorCirclePoints.push(x1)
          colorCirclePoints.push(y1)
          colorCirclePoints.push(preX2)
          colorCirclePoints.push(preY2)
          colorCirclePoints.push(x1)
          colorCirclePoints.push(y1)
          colorCirclePoints.push(x2)
          colorCirclePoints.push(y2)
          const precolor = colors[i - 1]
          const color = i < colors.length ? colors[i] : precolor
          colorCirclePointsColors.push(precolor.R / 255)
          colorCirclePointsColors.push(precolor.G / 255)
          colorCirclePointsColors.push(precolor.B / 255)
          colorCirclePointsColors.push(1.0)
          colorCirclePointsColors.push(precolor.R / 255)
          colorCirclePointsColors.push(precolor.G / 255)
          colorCirclePointsColors.push(precolor.B / 255)
          colorCirclePointsColors.push(1.0)
          colorCirclePointsColors.push(color.R / 255)
          colorCirclePointsColors.push(color.G / 255)
          colorCirclePointsColors.push(color.B / 255)
          colorCirclePointsColors.push(1.0)
          colorCirclePointsColors.push(precolor.R / 255)
          colorCirclePointsColors.push(precolor.G / 255)
          colorCirclePointsColors.push(precolor.B / 255)
          colorCirclePointsColors.push(1.0)
          colorCirclePointsColors.push(color.R / 255)
          colorCirclePointsColors.push(color.G / 255)
          colorCirclePointsColors.push(color.B / 255)
          colorCirclePointsColors.push(1.0)
          colorCirclePointsColors.push(color.R / 255)
          colorCirclePointsColors.push(color.G / 255)
          colorCirclePointsColors.push(color.B / 255)
          colorCirclePointsColors.push(1.0)
        }
        preX1 = x1
        preY1 = y1
        preX2 = x2
        preY2 = y2
      }
      _drawTranglesWithVaringColor(
        colorCirclePoints,
        _compassConfig.compassMatrix,
        colorCirclePointsColors
      )
    }
  }

  /**
   * 绘制车位
   */
  function _drawCarPosition () {
    if (_compassConfig.compassCarPositionRotation == null) {
      // _compassConfig.compassCarPositionRotation = 0
      return
    }
    if (!_compassConfig.compassCarPositionMatrix) {
      // 根据分辨率直接生成矩阵
      let projectionMatrix = m3.projection(
        _gl.canvas.clientWidth,
        _gl.canvas.clientHeight
      )
      // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
      const translationMatrix = m3.translation(0, _gl.canvas.clientHeight)
      projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
      // scaling 绕原点翻转(-1 ~ 1)
      projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
      projectionMatrix = m3.multiply(
        projectionMatrix,
        m3.translation(_gl.canvas.clientWidth / 2, _gl.canvas.clientHeight / 2)
      )
      // _axisMatrix = projectionMatrix
      projectionMatrix = m3.multiply(
        projectionMatrix,
        m3.rotation(_compassConfig.compassCarPositionRotation)
      )
      _compassConfig.compassCarPositionMatrix = projectionMatrix
    }
    const banjing = _container.clientHeight / 2 - 5
    const points = [
      0,
      banjing - 20,
      8,
      banjing - 45,
      -8,
      banjing - 45,
      8,
      banjing - 45,
      -8,
      banjing - 45,
      -8,
      -banjing + 20,
      8,
      banjing - 45,
      -8,
      -banjing + 20,
      8,
      -banjing + 20
    ]
    _drawTransparentTrangles(points, _compassConfig.compassCarPositionMatrix, {
      r: 1,
      g: 1,
      b: 1,
      a: 0.4
    })
    // _drawTrangles(points, _compassConfig.compassCarPositionMatrix, {r: 1, g: 1, b: 1})
  }

  /**
   * 绘制罗盘上的点
   */
  function _drawCompassPoints () {
    if (_compassConfig.comapssShowPoints.length === 0) {
      _compassConfig.comapssShowPointsColors = []
      // 计算哪些点需要被展示
      _compassConfig.comapssPoints.forEach((item) => {
        const currentRotation = 2 * Math.PI * (item.angle / 360)
        if (
          Math.abs(_compassConfig.pointShowJiaoDuChange) < 2 * Math.PI &&
          _compassConfig.pointShowJiaoDuChange != null &&
          _compassConfig.pointShowJiaoDuChange != 0
        ) {
          if (_compassConfig.pointShowJiaoDuChange < 0) {
            // 逆时针
            if (_compassConfig.startRotation > _compassConfig.stopRotation) {
              // 没有越过y轴
              if (
                currentRotation > _compassConfig.stopRotation &&
                currentRotation < _compassConfig.startRotation
              ) {
                const drawPoints = _transfromCompassPointsToRect(
                  item.xToRect,
                  item.yToRect,
                  currentRotation
                )
                _compassConfig.comapssShowPoints =
                  _compassConfig.comapssShowPoints.concat(drawPoints)
                _compassConfig.compassShowPointSizes.push(
                  _compassConfig.pointSize
                )
              }
            } else {
              // 越过y轴
              if (
                currentRotation > _compassConfig.stopRotation ||
                currentRotation < _compassConfig.startRotation
              ) {
                const drawPoints = _transfromCompassPointsToRect(
                  item.xToRect,
                  item.yToRect,
                  currentRotation
                )
                _compassConfig.comapssShowPoints =
                  _compassConfig.comapssShowPoints.concat(drawPoints)
                _compassConfig.compassShowPointSizes.push(
                  _compassConfig.pointSize
                )
              }
            }
          } else {
            // 顺时针
            if (_compassConfig.stopRotation > _compassConfig.startRotation) {
              // 没有越过y轴
              if (
                currentRotation > _compassConfig.startRotation &&
                currentRotation < _compassConfig.stopRotation
              ) {
                const drawPoints = _transfromCompassPointsToRect(
                  item.xToRect,
                  item.yToRect,
                  currentRotation
                )
                _compassConfig.comapssShowPoints =
                  _compassConfig.comapssShowPoints.concat(drawPoints)
                _compassConfig.compassShowPointSizes.push(
                  _compassConfig.pointSize
                )
              }
            } else {
              if (
                currentRotation > _compassConfig.startRotation ||
                currentRotation < _compassConfig.stopRotation
              ) {
                const drawPoints = _transfromCompassPointsToRect(
                  item.xToRect,
                  item.yToRect,
                  currentRotation
                )
                _compassConfig.comapssShowPoints =
                  _compassConfig.comapssShowPoints.concat(drawPoints)
                _compassConfig.compassShowPointSizes.push(
                  _compassConfig.pointSize
                )
              }
            }
          }
        } else {
          const drawPoints = _transfromCompassPointsToRect(
            item.xToRect,
            item.yToRect,
            currentRotation
          )
          _compassConfig.comapssShowPoints =
            _compassConfig.comapssShowPoints.concat(drawPoints)
          _compassConfig.compassShowPointSizes.push(_compassConfig.pointSize)
        }
        _compassConfig.comapssShowPointsColors =
          _compassConfig.comapssShowPointsColors.concat([
            item.color.r,
            item.color.g,
            item.color.b,
            1,
            item.color.r,
            item.color.g,
            item.color.b,
            1,
            item.color.r,
            item.color.g,
            item.color.b,
            1,
            item.color.r,
            item.color.g,
            item.color.b,
            1,
            item.color.r,
            item.color.g,
            item.color.b,
            1,
            item.color.r,
            item.color.g,
            item.color.b,
            1
          ])
      })
    }
    _drawTranglesWithVaringColor(
      _compassConfig.comapssShowPoints,
      _compassConfig.compassMatrix,
      _compassConfig.comapssShowPointsColors
    )
    // _drawTrangles(_compassConfig.comapssShowPoints, _compassConfig.compassMatrix, {r: 0, g: 1, b: 1})
    // _drawWidthPoints(_compassConfig.comapssShowPoints, _compassConfig.compassMatrix, _compassConfig.compassShowPointSizes, {r: 0, g: 1, b: 1})
    // _drawLineGroup(_compassConfig.comapssShowPoints, _compassConfig.compassMatrix,{r: 0, g: 1, b: 1})
  }

  /**
   * 将罗盘图上的点转换成需要绘制的有宽度的线的坐标
   */
  function _transfromCompassPointsToRect (x, y, rotation) {
    let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1]
    matrix = m3.rotation(rotation, matrix)
    const banjing = _container.clientHeight / 2 - 10
    const width = 2
    const points = [
      [x - width / 2, banjing],
      [x + width / 2, banjing],
      [x - width / 2, banjing - y],
      [x - width / 2, banjing - y],
      [x + width / 2, banjing - y],
      [x + width / 2, banjing]
    ]
    let tansfromedPoints = []
    points.forEach((point) => {
      tansfromedPoints = tansfromedPoints.concat(
        m3.transformPoint(matrix, point)
      )
    })
    // //console.log(tansfromedPoints)
    return tansfromedPoints
  }

  /**
   * 绘制罗盘指针
   */
  function _drawCompassPointer () {
    if (_compassConfig.compassPointRotation == null) {
      return
    }
    // 根据分辨率直接生成矩阵
    let projectionMatrix = m3.projection(
      _gl.canvas.clientWidth,
      _gl.canvas.clientHeight
    )
    // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
    const translationMatrix = m3.translation(0, _gl.canvas.clientHeight)
    projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
    // scaling 绕原点翻转(-1 ~ 1)
    projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
    projectionMatrix = m3.multiply(
      projectionMatrix,
      m3.translation(_gl.canvas.clientWidth / 2, _gl.canvas.clientHeight / 2)
    )
    // _axisMatrix = projectionMatrix
    projectionMatrix = m3.multiply(
      projectionMatrix,
      m3.rotation(_compassConfig.compassPointRotation)
    )

    if (_compassConfig.compassScaleRotation) {
      projectionMatrix = m3.multiply(
        projectionMatrix,
        m3.rotation(_compassConfig.compassScaleRotation)
      )
    }
    _compassConfig.compassPointMatrix = projectionMatrix

    const width = 3
    const points = [
      width,
      _container.clientHeight / 2 - 5,
      width,
      0,
      -width,
      0,
      -width,
      0,
      -width,
      _container.clientHeight / 2 - 5,
      width,
      _container.clientHeight / 2 - 5
    ]
    _drawTrangles(points, _compassConfig.compassPointMatrix, {
      r: 1,
      g: 0,
      b: 0
    })
    // _drawLineGroupWithLineStrip(points, _compassPointMatrix, {r: 1, g: 1, b: 1})
  }

  /**
   * 绘制鼠标拖动区域的扇形
   */
  function _drawMouseStrap () {
    if (_compassConfig.sectorPoints && _compassConfig.sectorPoints.length > 0) {
      _drawTransparentTrangleFan(
        _compassConfig.sectorPoints,
        _compassConfig.compassMatrix,
        { r: 1, g: 1, b: 1 }
      )
    }
  }

  /**
   * 填充axis内部颜色为黑色
   */
  function _fillAxisArea () {
    // 设置使用的着色器和viewport
    _gl.useProgram(_lineShaderProgram)
    _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
    // 循环绘制series
    _Series.forEach((series, index) => {
      if (!_axisMatrix) {
        // 计算矩阵
        // 根据分辨率直接生成矩阵
        let projectionMatrix = m3.projection(
          _gl.canvas.clientWidth,
          _gl.canvas.clientHeight
        )
        // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
        const translationMatrix = m3.translation(0, _gl.canvas.clientHeight)
        projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
        // scaling 绕原点翻转(-1 ~ 1)
        projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
        _axisMatrix = projectionMatrix
      }
      // 设置使用的着色器和viewport
      _gl.useProgram(_lineShaderProgram)
      _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
      const points = [
        series.yAxis.padding,
        series.xAxis.padding,
        series.yAxis.padding,
        _container.clientHeight - series.xAxis.defaltPadding,
        _container.clientWidth - series.yAxis.defaltPadding,
        _container.clientHeight - series.xAxis.defaltPadding,
        _container.clientWidth - series.yAxis.defaltPadding,
        _container.clientHeight - series.xAxis.defaltPadding,
        _container.clientWidth - series.yAxis.defaltPadding,
        series.xAxis.padding,
        series.yAxis.padding,
        series.xAxis.padding
      ]
      _drawTrangles(points, _axisMatrix, { r: 0, g: 0, b: 0 })
    })
  }

  /**
   * 绘制xaxis和yaxis
   */
  function _drawSeriesAxis () {
    // 设置使用的着色器和viewport
    _gl.useProgram(_lineShaderProgram)
    _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
    if (!_axisMatrix) {
      // 计算矩阵
      // 根据分辨率直接生成矩阵
      let projectionMatrix = m3.projection(
        _gl.canvas.clientWidth,
        _gl.canvas.clientHeight
      )
      // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
      const translationMatrix = m3.translation(0, _gl.canvas.clientHeight)
      projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
      // scaling 绕原点翻转(-1 ~ 1)
      projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
      _axisMatrix = projectionMatrix
    }

    // 循环绘制series
    _Series.forEach((item, index) => {
      // 绘制X轴单位
      if (item.axisXUnits && item.axisXUnits.text) {
        _textCtx.font = '12px sans-serif'
        _textCtx.fillStyle = '#9fb7b7'
        const axisXUnitsX =
          item.axisXUnits.left -
          _textCtx.measureText(item.axisXUnits.text).width / 2
        const axisXUnitsY = item.axisXUnits.top - 8
        _textCtx.fillText(item.axisXUnits.text, axisXUnitsX, axisXUnitsY)
      }

      // 绘制Y轴单位
      if (item.axisYUnits && item.axisYUnits.text) {
        _textCtx.font = '12px sans-serif'
        _textCtx.fillStyle = '#9fb7b7'
        const axisXUnitsX = item.axisYUnits.left
        let axisXUnitsY =
          item.axisYUnits.top -
          _textCtx.measureText(item.axisYUnits.text).width / 2
        // let content = item.axisYUnits.text.split('').reverse().join(',') // 反转数组
        const content = item.axisYUnits.text
        for (let i = 0; i < content.length; i++) {
          const str = content.slice(i, i + 1).toString()
          if (str.match(/[A-Za-z0-9]/)) {
            // 非汉字 旋转
            _textCtx.save()
            _textCtx.translate(axisXUnitsX, axisXUnitsY)
            _textCtx.rotate((90 * Math.PI) / 180) // 逆时针转90度
            _textCtx.textBaseline = 'bottom'
            _textCtx.fillText(str, 0, 0)
            _textCtx.restore()
            axisXUnitsY += _textCtx.measureText(str).width // 计算文字宽度
          } else if (str.match(/[\u4E00-\u9FA5]/)) {
            _textCtx.save()
            _textCtx.textBaseline = 'top'
            _textCtx.fillText(str, axisXUnitsX, axisXUnitsY)
            _textCtx.restore()
            axisXUnitsY += _textCtx.measureText(str).width // 计算文字宽度
          }
        }
      }

      // 绘制右上角提示信息
      if (
        item.tooltip &&
        item.tooltip.value1 !== '' &&
        item.tooltip.value2 !== ''
      ) {
        _textCtx.font = '12px sans-serif'
        _textCtx.fillStyle = '#9fb7b7'
        if (
          item.tooltip.value1 !== undefined &&
          item.tooltip.value2 !== undefined
        ) {
          const str1 =
            item.tooltip.value1 === null
              ? ''
              : `频率: ${Number(item.tooltip.value1).toFixed(3)}MHz`
          const str2 =
            item.tooltip.value2 === null
              ? ''
              : `强度: ${Number(item.tooltip.value2).toFixed(2)}dBm`
          const str3 =
            item.tooltip.value3 === undefined
              ? ''
              : `增益: ${item.tooltip.value3}`
          const str = `${str1} ${str2} ${str3}`
          const axisXUnitsX =
            item.tooltip.left - _textCtx.measureText(str).width - 20
          const axisXUnitsY = item.tooltip.top + 8
          _textCtx.fillText(str, axisXUnitsX, axisXUnitsY)
        }
      }

      // 绘制标题文字
      if (item.title && item.title.text) {
        _textCtx.font = 'bold 18px sans-serif'
        _textCtx.fillStyle = '#9fb7b7'
        const titleX =
          item.title.left - _textCtx.measureText(item.title.text).width / 2
        const titleY = item.title.top + 10
        _textCtx.fillText(item.title.text, titleX, titleY)
      }

      // 因为要计算文字长度 所以先设置文字字体和大小
      _textCtx.fillStyle =
        'rgb(' +
        item.yAxis.color.r * 255 +
        ',' +
        item.yAxis.color.g * 255 +
        ',' +
        item.yAxis.color.b * 255 +
        ')'
      _textCtx.font = '10px sans-serif'

      const realPaddingX = item.xAxis.padding
      const realPaddingY = item.yAxis.padding

      if (_config.type === 'pubu' && item.direction === 'rightToLeft') {
        // x轴和y轴对换
        if (item.yAxis.points.length === 0) {
          // 绘制网格线
          let tablePoints = []
          // 先清空文字缓存
          item.yAxis.words = []
          // 一条直线
          item.yAxis.points = item.yAxis.points.concat([
            realPaddingY,
            realPaddingX,
            realPaddingY,
            _gl.canvas.clientHeight - item.xAxis.defaltPadding
          ])

          const yAxisNum = item.xAxis.markNum
          const yMarkInterval =
            (_container.clientHeight -
              item.xAxis.padding -
              item.xAxis.defaltPadding) /
            item.yAxis.markNum
          const tmpYMarkStartY = realPaddingX
          const startYvalue = item.xAxis.interval[0]
          const endYvalue = item.xAxis.interval[1]
          const yValueMarkInterval =
            (item.xAxis.interval[1] - item.xAxis.interval[0]) / yAxisNum

          for (let j = 0; j <= yAxisNum; j++) {
            const tmpY = tmpYMarkStartY + j * yMarkInterval
            // let tmpYvalue = (startYvalue + (j * yValueMarkInterval)).toFixed(2)
            const tmpYvalue = (endYvalue - j * yValueMarkInterval).toFixed(2)
            item.yAxis.points = item.yAxis.points.concat([
              realPaddingY,
              tmpY,
              realPaddingY - 5,
              tmpY
            ])
            if (_config.type === 'line') {
              tablePoints = tablePoints.concat([
                realPaddingY,
                tmpY,
                _container.clientWidth - item.yAxis.defaltPadding,
                tmpY
              ])
            }
            let ystr = ''
            if (item.xAxis.xAxisMarkFormatter) {
              ystr = item.xAxis.xAxisMarkFormatter(tmpYvalue)
            } else {
              ystr = tmpYvalue.toString()
            }
            // item.yAxis.words.push({
            //   str: ystr,
            //   x: realPaddingY - (_textCtx.measureText(ystr).width) - 8,
            //   y: _container.height - tmpY + 4
            // })
            if (_config.type === 'line') {
              item.yTablePoints = tablePoints
            }
          }
        }
        if (item.xAxis.points.length === 0) {
          // 绘制网格线
          let tablePoints = []
          // 先清空文字缓存
          item.xAxis.words = []
          item.xAxis.points = item.xAxis.points.concat([
            realPaddingY,
            realPaddingX,
            _gl.canvas.clientWidth - item.yAxis.defaltPadding,
            realPaddingX
          ])
          // 直线上的多个节点
          const xAxisNum = item.yAxis.markNum
          const xMarkInterval =
            (_container.clientWidth -
              item.yAxis.padding -
              item.yAxis.defaltPadding) /
            xAxisNum
          const tmpXMarkStartX = realPaddingY
          const startXvalue = item.yAxis.interval[0]
          const xValueMarkInterval =
            (item.yAxis.interval[1] - item.yAxis.interval[0]) / xAxisNum

          for (let i = 0; i <= xAxisNum; i++) {
            const tmpX = tmpXMarkStartX + i * xMarkInterval
            const tmpXvalue = (startXvalue + i * xValueMarkInterval).toFixed(2)
            item.xAxis.points = item.xAxis.points.concat([
              tmpX,
              realPaddingX,
              tmpX,
              realPaddingX - 5
            ])
            if (_config.type === 'line') {
              tablePoints = tablePoints.concat([
                tmpX,
                realPaddingX,
                tmpX,
                _container.clientHeight - item.xAxis.defaltPadding
              ])
            }
            // ----------------------------------------
            // y轴x轴对调了！！！
            // ----------------------------------------
            let xstr = ''
            if (item.yAxis.yAxisMarkFormatter) {
              xstr = item.yAxis.yAxisMarkFormatter(tmpXvalue)
            } else {
              xstr = tmpXvalue.toString()
            }
            item.xAxis.words.push({
              str: xstr,
              x: tmpX - _textCtx.measureText(xstr).width / 2,
              // 减去了字体高度和 小标签的高度
              y: _container.height - (realPaddingX - 10 - 5)
            })
            if (_config.type === 'line') {
              item.xTablePoints = tablePoints
            }
            // //console.log(item.xAxis.points)
          }
        }
        if (_config.type === 'line') {
          _drawLineGroup(item.xTablePoints, _axisMatrix, {
            r: 0,
            g: 80 / 255,
            b: 0
          })
          _drawLineGroup(item.yTablePoints, _axisMatrix, {
            r: 0,
            g: 80 / 255,
            b: 0
          })
        }
      } else {
        // 先计算xaxis yaxis各自的点的坐标
        if (item.yAxis.points.length === 0) {
          // 绘制网格线
          let tablePoints = []
          // 先清空文字缓存
          item.yAxis.words = []
          // 一条直线
          item.yAxis.points = item.yAxis.points.concat([
            realPaddingY,
            realPaddingX,
            realPaddingY,
            _gl.canvas.clientHeight - item.xAxis.defaltPadding
          ])

          const yMarkInterval =
            (_container.clientHeight -
              item.xAxis.padding -
              item.xAxis.defaltPadding) /
            item.yAxis.markNum
          const tmpYMarkStartY = realPaddingX
          const startYvalue = item.yAxis.interval[0]
          const yValueMarkInterval =
            (item.yAxis.interval[1] - item.yAxis.interval[0]) /
            item.yAxis.markNum

          for (let j = 0; j <= item.yAxis.markNum; j++) {
            const tmpY = tmpYMarkStartY + j * yMarkInterval
            const tmpYvalue = parseInt(startYvalue + j * yValueMarkInterval)

            item.yAxis.points = item.yAxis.points.concat([
              realPaddingY,
              tmpY,
              realPaddingY - 5,
              tmpY
            ])
            if (_config.type === 'line') {
              tablePoints = tablePoints.concat([
                realPaddingY,
                tmpY,
                _container.clientWidth - item.yAxis.defaltPadding,
                tmpY
              ])
            }
            let ystr = ''
            if (item.yAxis.yAxisMarkFormatter) {
              ystr = item.yAxis.yAxisMarkFormatter(tmpYvalue)
            } else {
              ystr = tmpYvalue.toString()
            }
            if (item.yAxis.markNum != 1) {
              // 屏蔽窄带话音y轴数据
              item.yAxis.words.push({
                str: ystr,
                x: realPaddingY - _textCtx.measureText(ystr).width - 8,
                y: _container.height - tmpY + 4
              })
            }

            if (_config.type === 'line') {
              item.yTablePoints = tablePoints
            }
          }
        }

        if (item.xAxis.points.length === 0) {
          // 绘制网格线
          let tablePoints = []
          // 先清空文字缓存
          item.xAxis.words = []
          item.xAxis.points = item.xAxis.points.concat([
            realPaddingY,
            realPaddingX,
            _gl.canvas.clientWidth - item.yAxis.defaltPadding,
            realPaddingX
          ])
          // 直线上的多个节点
          const xMarkInterval =
            (_container.clientWidth -
              item.yAxis.padding -
              item.yAxis.defaltPadding) /
            item.xAxis.markNum
          const tmpXMarkStartX = realPaddingY
          const startXvalue = item.xAxis.interval[0]
          const xValueMarkInterval =
            (item.xAxis.interval[1] - item.xAxis.interval[0]) /
            item.xAxis.markNum

          let realMarkNum = item.xAxis.markNum
          let realxValueMarkInterval = xValueMarkInterval
          let realxMarkInterval = xMarkInterval
          if (xValueMarkInterval < 5 * 1000000) {
          } else if (
            xValueMarkInterval > 5 * 1000000 &&
            xValueMarkInterval < 10 * 1000000
          ) {
            realxValueMarkInterval = 10 * 1000000
          } else if (
            xValueMarkInterval > 10 * 1000000 &&
            xValueMarkInterval < 15 * 1000000
          ) {
            realxValueMarkInterval = 15 * 1000000
          } else if (
            xValueMarkInterval > 15 * 1000000 &&
            xValueMarkInterval < 20 * 1000000
          ) {
            realxValueMarkInterval = 20 * 1000000
          } else if (
            xValueMarkInterval > 25 * 1000000 &&
            xValueMarkInterval < 30 * 1000000
          ) {
            realxValueMarkInterval = 30 * 1000000
          } else if (
            xValueMarkInterval > 30 * 1000000 &&
            xValueMarkInterval < 50 * 1000000
          ) {
            realxValueMarkInterval = 50 * 1000000
          } else if (
            xValueMarkInterval > 30 * 1000000 &&
            xValueMarkInterval < 35 * 1000000
          ) {
            realxValueMarkInterval = 35 * 1000000
          } else if (
            xValueMarkInterval > 35 * 1000000 &&
            xValueMarkInterval < 40 * 1000000
          ) {
            realxValueMarkInterval = 40 * 1000000
          } else if (
            xValueMarkInterval > 40 * 1000000 &&
            xValueMarkInterval < 45 * 1000000
          ) {
            realxValueMarkInterval = 45 * 1000000
          } else if (
            xValueMarkInterval > 45 * 1000000 &&
            xValueMarkInterval < 50 * 1000000
          ) {
            realxValueMarkInterval = 50 * 1000000
          }
          realMarkNum = Math.floor(
            (item.xAxis.interval[1] - item.xAxis.interval[0]) /
              realxValueMarkInterval
          )
          realxMarkInterval =
            (realxValueMarkInterval /
              (item.xAxis.interval[1] - item.xAxis.interval[0])) *
            (_container.clientWidth -
              item.yAxis.padding -
              item.yAxis.defaltPadding)

          for (let i = 0; i <= realMarkNum; i++) {
            const tmpX = tmpXMarkStartX + i * realxMarkInterval
            const tmpXvalue = (
              startXvalue +
              i * realxValueMarkInterval
            ).toFixed(2)
            item.xAxis.points = item.xAxis.points.concat([
              tmpX,
              realPaddingX,
              tmpX,
              realPaddingX - 5
            ])
            if (_config.type === 'line') {
              tablePoints = tablePoints.concat([
                tmpX,
                realPaddingX,
                tmpX,
                _container.clientHeight - item.xAxis.defaltPadding
              ])
            }
            let xstr = ''
            if (item.xAxis.xAxisMarkFormatter) {
              xstr = item.xAxis.xAxisMarkFormatter(tmpXvalue)
            } else {
              xstr = tmpXvalue.toString()
            }
            item.xAxis.words.push({
              str: xstr,
              x: tmpX - _textCtx.measureText(xstr).width / 2,
              // 减去了字体高度和 小标签的高度
              y: _container.height - (realPaddingX - 10 - 5)
            })
            if (_config.type === 'line') {
              item.xTablePoints = tablePoints
            }
            // //console.log(item.xAxis.points)
          }
        }
        if (_config.type === 'line') {
          _drawLineGroup(item.xTablePoints, _axisMatrix, {
            r: 0,
            g: 80 / 255,
            b: 0
          })
          _drawLineGroup(item.yTablePoints, _axisMatrix, {
            r: 0,
            g: 80 / 255,
            b: 0
          })
        }
      }
      // 绘制x轴
      _drawLineGroup(item.xAxis.points, _axisMatrix, item.xAxis.color)
      item.xAxis.words.forEach((word) => {
        _textCtx.fillText(word.str, word.x, word.y)
      })

      // 绘制y轴
      _drawLineGroup(item.yAxis.points, _axisMatrix, item.yAxis.color)
      item.yAxis.words.forEach((word) => {
        _textCtx.fillText(word.str, word.x, word.y)
      })
    })
  }

  // /**
  //  * 绘制线
  //  */
  // function _drawSeriesLine () {
  //   _Series.forEach((series, index) => {
  //       // 设置使用的着色器和viewport
  //     _gl.useProgram(_lineShaderProgram)
  //     _gl.viewport(series.yAxis.padding, series.xAxis.padding, _gl.canvas.width - series.yAxis.padding - series.yAxis.defaltPadding, _gl.canvas.height - series.xAxis.padding - series.xAxis.defaltPadding)

  //     if (!series._linesMatrix) {
  //       // 根据分辨率直接生成矩阵
  //       // eslint-disable-next-line no-undef
  //       var projectionMatrix = m3.projection(_gl.canvas.clientWidth - series.yAxis.padding - series.yAxis.defaltPadding, _gl.canvas.clientHeight - series.xAxis.padding - series.xAxis.defaltPadding)
  //       // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
  //       var translationMatrix = m3.translation(0, _gl.canvas.clientHeight - series.xAxis.padding - series.xAxis.defaltPadding)
  //       projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
  //       // scaling 绕原点翻转(-1 ~ 1)
  //       projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
  //       series._linesMatrix = projectionMatrix
  //     }
  //     series.lines.forEach((line) => {
  //       if (line.transferedData.length === 0) {
  //           // 需要重新计算坐标
  //         for (let i = 0; i < line.data.length; i += 2) {
  //           let x = line.data[i]
  //           let y = line.data[i + 1]
  //           let newXPercent = ((x - series.xAxis.interval[0]) / (series.xAxis.interval[1] - series.xAxis.interval[0]))
  //           let transformedX = (_container.clientWidth - series.yAxis.padding - series.yAxis.defaltPadding) * newXPercent
  //           let newYPercent = ((y - series.yAxis.interval[0]) / (series.yAxis.interval[1] - series.yAxis.interval[0]))
  //           let transformedY = (_container.clientHeight - series.xAxis.padding - series.xAxis.defaltPadding) * newYPercent
  //           if (i === 0 || i === line.data.length - 2) {
  //             line.transferedData.push(transformedX)
  //             line.transferedData.push(transformedY)
  //           } else {
  //             line.transferedData.push(transformedX)
  //             line.transferedData.push(transformedY)
  //             line.transferedData.push(transformedX)
  //             line.transferedData.push(transformedY)
  //           }
  //         }
  //       }
  //       _drawLineGroup(line.transferedData, series._linesMatrix, line.color)
  //     })
  //   })
  // }

  /**
   * 绘制线
   */
  function _drawSeriesLine () {
    _Series.forEach((series, index) => {
      // 设置使用的着色器和viewport
      _gl.useProgram(_lineShaderProgram)
      _gl.viewport(
        series.yAxis.padding,
        series.xAxis.padding,
        _gl.canvas.width - series.yAxis.padding - series.yAxis.defaltPadding,
        _gl.canvas.height - series.xAxis.padding - series.xAxis.defaltPadding
      )

      if (!series._linesMatrix) {
        // 根据分辨率直接生成矩阵
        // eslint-disable-next-line no-undef
        let projectionMatrix = m3.projection(
          _gl.canvas.clientWidth -
            series.yAxis.padding -
            series.yAxis.defaltPadding,
          _gl.canvas.clientHeight -
            series.xAxis.padding -
            series.xAxis.defaltPadding
        )
        // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
        const translationMatrix = m3.translation(
          0,
          _gl.canvas.clientHeight -
            series.xAxis.padding -
            series.xAxis.defaltPadding
        )
        projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
        // scaling 绕原点翻转(-1 ~ 1)
        projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))

        const xTransfer =
          (series.xAxis.interval[1] - series.xAxis.interval[0]) /
          (_container.clientWidth -
            series.yAxis.padding -
            series.yAxis.defaltPadding)
        const yTransfer =
          (series.yAxis.interval[1] - series.yAxis.interval[0]) /
          (_container.clientHeight -
            series.xAxis.padding -
            series.xAxis.defaltPadding)
        projectionMatrix = m3.multiply(
          projectionMatrix,
          m3.scaling(1 / xTransfer, 1 / yTransfer)
        )
        projectionMatrix = m3.multiply(
          projectionMatrix,
          m3.translation(-series.xAxis.interval[0], -series.yAxis.interval[0])
        )
        series._linesMatrix = projectionMatrix
      }
      // _drawLineGroup([0, 0, 546.13, 204, 546.13, 204, 0, 204, 546.13, 215, 546.13, 95, 546.13, 95, 0, 95], series._linesMatrix, {r: 1, g: 1, b: 1})
      series.lines.forEach((line) => {
        // if (line.transferedData.length === 0) {
        //   // 需要重新计算坐标
        //   for (let i = 0; i < line.data.length; i += 2) {
        //     let x = line.data[i]
        //     let y = line.data[i + 1]
        //     let newXPercent = ((x - series.xAxis.interval[0]) / (series.xAxis.interval[1] - series.xAxis.interval[0]))
        //     let transformedX = (_container.clientWidth - series.yAxis.padding - series.yAxis.defaltPadding) * newXPercent
        //     let newYPercent = ((y - series.yAxis.interval[0]) / (series.yAxis.interval[1] - series.yAxis.interval[0]))
        //     let transformedY = (_container.clientHeight - series.xAxis.padding - series.xAxis.defaltPadding) * newYPercent
        //     if (i === 0 || i === line.data.length - 2) {
        //       line.transferedData.push(transformedX)
        //       line.transferedData.push(transformedY)
        //     } else {
        //       line.transferedData.push(transformedX)
        //       line.transferedData.push(transformedY)
        //       line.transferedData.push(transformedX)
        //       line.transferedData.push(transformedY)
        //     }
        //   }
        // }
        if (line.visible) {
          _drawLineGroupWithLineStrip(
            line.data,
            series._linesMatrix,
            line.color
          )
        }
      })
    })
  }

  /**
   * 绘制鼠标拖动的矩形
   */
  function _drawSeriesMouseStrapRect () {
    _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
    _Series.forEach((series) => {
      if (series.mouseStrapPoints && series.mouseStrapPoints.length !== 0) {
        // _drawLineGroup(series.mouseStrapPoints, _axisMatrix, {r: 1, g: 1, b: 1})
        _drawTransparentRect(series.mouseStrapPoints, _axisMatrix, {
          r: 1,
          g: 1,
          b: 1,
          a: 1
        })
      }
    })
  }

  /**
   * 绘制标记线
   */
  function _drawMarkLines () {
    _gl.useProgram(_lineShaderProgram)
    _gl.viewport(0, 0, _container.clientWidth, _container.clientHeight)

    _Series.forEach((series) => {
      series.xAxis.markLines.forEach((markLine) => {
        if (markLine.visible == false) {
          return
        }
        if (markLine.points.length === 0) {
          if (
            markLine.value < series.xAxis.interval[0] ||
            markLine.value > series.xAxis.interval[1]
          ) {
            return
          }
          // 计算点
          const transformedX = _getXPixesByXvalue(markLine.value, series)

          markLine.pixes = transformedX
          markLine.points.push(transformedX)
          markLine.points.push(series.xAxis.padding)
          markLine.points.push(transformedX)
          markLine.points.push(
            _container.clientHeight - series.xAxis.defaltPadding
          )

          // _drawLineGroup(markLine.points, _axisMatrix, markLine.color)
          _drawYLineWithWidth(
            markLine.points[0],
            markLine.points[1],
            markLine.points[2],
            markLine.points[3],
            1,
            _axisMatrix,
            markLine.color
          )
        } else {
          // _drawLineGroup(markLine.points, _axisMatrix, markLine.color)

          _drawYLineWithWidth(
            markLine.points[0],
            markLine.points[1],
            markLine.points[2],
            markLine.points[3],
            1,
            _axisMatrix,
            markLine.color
          )
        }
      })
      series.yAxis.markLines.forEach((markLine) => {
        if (markLine.points.length === 0) {
          if (
            markLine.value < series.yAxis.interval[0] ||
            markLine.value > series.yAxis.interval[1]
          ) {
            return
          }
          // 计算点
          const transformedY = _getYPixesByYvalue(markLine.value, series)
          markLine.pixes = transformedY
          markLine.points.push(series.yAxis.padding)
          markLine.points.push(transformedY)
          markLine.points.push(
            _container.clientWidth - series.yAxis.defaltPadding
          )
          markLine.points.push(transformedY)

          // _drawLineGroup(markLine.points, _axisMatrix, markLine.color)
          _drawXLineWithWidth(
            markLine.points[0],
            markLine.points[1],
            markLine.points[2],
            markLine.points[3],
            1,
            _axisMatrix,
            markLine.color
          )
        } else {
          // _drawLineGroup(markLine.points, _axisMatrix, markLine.color)

          _drawXLineWithWidth(
            markLine.points[0],
            markLine.points[1],
            markLine.points[2],
            markLine.points[3],
            1,
            _axisMatrix,
            markLine.color
          )
        }
      })
    })
  }
  /**
   * 绘制x轴的标记区域
   */
  function _drawXMarkZones () {
    _Series.forEach((series) => {
      if (!series._linesMatrix) {
        // 根据分辨率直接生成矩阵
        // eslint-disable-next-line no-undef
        let projectionMatrix = m3.projection(
          _gl.canvas.clientWidth -
            series.yAxis.padding -
            series.yAxis.defaltPadding,
          _gl.canvas.clientHeight -
            series.xAxis.padding -
            series.xAxis.defaltPadding
        )
        // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
        const translationMatrix = m3.translation(
          0,
          _gl.canvas.clientHeight -
            series.xAxis.padding -
            series.xAxis.defaltPadding
        )
        projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
        // scaling 绕原点翻转(-1 ~ 1)
        projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))

        const xTransfer =
          (series.xAxis.interval[1] - series.xAxis.interval[0]) /
          (_container.clientWidth -
            series.yAxis.padding -
            series.yAxis.defaltPadding)
        const yTransfer =
          (series.yAxis.interval[1] - series.yAxis.interval[0]) /
          (_container.clientHeight -
            series.xAxis.padding -
            series.xAxis.defaltPadding)
        projectionMatrix = m3.multiply(
          projectionMatrix,
          m3.scaling(1 / xTransfer, 1 / yTransfer)
        )
        projectionMatrix = m3.multiply(
          projectionMatrix,
          m3.translation(-series.xAxis.interval[0], -series.yAxis.interval[0])
        )
        series._linesMatrix = projectionMatrix
      }
      _gl.useProgram(_lineShaderProgram)
      _gl.viewport(
        series.yAxis.padding,
        series.xAxis.padding,
        _gl.canvas.width - series.yAxis.padding - series.yAxis.defaltPadding,
        _gl.canvas.height - series.xAxis.padding - series.xAxis.defaltPadding
      )

      if (
        !series.xAxis.markZonePoints ||
        series.xAxis.markZonePoints.length === 0
      ) {
        series.xAxis.markZoneWords = []
        series.xAxis.markZonePointColors = []
        series.xAxis.markZones.forEach((markZone) => {
          const transformedStartX = markZone.start
          const transformedendX = markZone.end

          const transformedstartY = series.yAxis.interval[0]
          const transformedendY = series.yAxis.interval[1]
          if (markZone.points.length === 0) {
            series.xAxis.markZonePoints = series.xAxis.markZonePoints.concat([
              transformedStartX,
              transformedstartY,
              transformedendX,
              transformedstartY,
              transformedStartX,
              transformedendY,
              transformedStartX,
              transformedendY,
              transformedendX,
              transformedendY,
              transformedendX,
              transformedstartY
            ])
            markZone.points = series.xAxis.markZonePoints
            series.xAxis.markZonePointColors =
              series.xAxis.markZonePointColors.concat([
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a
              ])
            // 绘制两条有宽度的边框
            if (markZone.borderColor) {
              const width =
                (2 /
                  (_container.clientWidth -
                    series.yAxis.padding -
                    -series.yAxis.defaltPadding)) *
                (series.xAxis.interval[1] - series.xAxis.interval[0])

              series.xAxis.markZonePoints = series.xAxis.markZonePoints.concat([
                transformedStartX - width,
                transformedstartY,
                transformedStartX,
                transformedstartY,
                transformedStartX - width,
                transformedendY,
                transformedStartX - width,
                transformedendY,
                transformedStartX,
                transformedendY,
                transformedStartX,
                transformedstartY,

                transformedendX,
                transformedstartY,
                transformedendX + width,
                transformedstartY,
                transformedendX,
                transformedendY,
                transformedendX,
                transformedendY,
                transformedendX + width,
                transformedendY,
                transformedendX + width,
                transformedstartY
              ])
              markZone.points = series.xAxis.markZonePoints
              series.xAxis.markZonePointColors =
                series.xAxis.markZonePointColors.concat([
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,

                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a
                ])
            }
            if (markZone.borderColor) {
            } else {
              // 添加在左右边界添加两条线
              series.xAxis.markZoneLRPoints =
                series.xAxis.markZoneLRPoints.concat([
                  transformedStartX,
                  transformedstartY,
                  transformedStartX,
                  transformedendY,
                  transformedendX,
                  transformedstartY,
                  transformedendX,
                  transformedendY
                ])
            }
            if (markZone.borderColor) {
            } else {
              series.xAxis.markZoneLRPointsColors =
                series.xAxis.markZoneLRPointsColors.concat([
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a,
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a,
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a,
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a
                ])
            }
          }

          const transformedRealEndX = _getXPixesByXvalueOnLineMatrix(
            markZone.end,
            series
          )
          series.xAxis.markZoneWords.push({
            x: transformedRealEndX + series.yAxis.padding,
            y: series.xAxis.defaltPadding + 15,
            str: markZone.str,
            // fillStyle:'rgb(' + markZone.color.r * 255 + ',' + markZone.color.g * 255 + ',' + markZone.color.b * 255 + ')'
            fillStyle: 'rgb(255,255,255)'
          })
          // _drawTransparentRect(markZone.points, series._linesMatrix, {r: 1, g: 1, b: 1})
          // _drawTranglesWithVaringColor(markZone.points, series._linesMatrix,markZone.pointColors)
        })
      }
      if (
        series.xAxis.markZonePoints &&
        series.xAxis.markZonePoints.length > 0
      ) {
        _drawTranglesWithVaringColor(
          series.xAxis.markZonePoints,
          series._linesMatrix,
          series.xAxis.markZonePointColors
        )
        _drawLineGroupWithVaringColor(
          series.xAxis.markZoneLRPoints,
          series._linesMatrix,
          series.xAxis.markZoneLRPointsColors
        )
      }
      // series.xAxis.markZonesHighLight.forEach((markZoneHighLight) => {
      //   let transformedStartX = markZoneHighLight.start
      //   let transformedendX = markZoneHighLight.end

      //   let transformedstartY = series.yAxis.interval[0]
      //   let transformedendY = series.yAxis.interval[1]
      //   if (markZoneHighLight.points.length === 0) {
      //     markZoneHighLight.points = [
      //       transformedStartX, transformedstartY,
      //       transformedendX, transformedstartY,
      //       transformedStartX, transformedendY,
      //       transformedStartX, transformedendY,
      //       transformedendX, transformedendY,
      //       transformedendX, transformedstartY
      //     ]
      //   }
      //   let transformedRealEndX = _getXPixesByXvalueOnLineMatrix(markZoneHighLight.end, series)
      //   series.xAxis.markZoneWords.push({
      //     x: transformedRealEndX + series.yAxis.padding,
      //     y:  series.xAxis.defaltPadding + 15,
      //     str: markZoneHighLight.str,
      //     fillStyle:'rgb(0,255,0)'
      //   })
      //   _drawTransparentRect(markZoneHighLight.points, series._linesMatrix, {r: 0, g: 1, b: 0})
      //   _drawLineGroup([
      //     transformedStartX,transformedstartY,
      //     transformedStartX,transformedendY,
      //     transformedendX,transformedstartY,
      //     transformedendX,transformedendY,
      //   ],series._linesMatrix,{r:1,g:1,b:1})
      // })
      if (series.xAxis.showMarkZoneWord) {
        // 绘制文字
        series.xAxis.markZoneWords.forEach((markZoneWord) => {
          if (
            markZoneWord.x >
              _container.clientWidth - series.yAxis.defaltPadding ||
            markZoneWord.x < series.yAxis.padding
          ) {
            return
          }
          _textCtx.fillStyle = markZoneWord.fillStyle
          _textCtx.font = '12px sans-serif'
          _textCtx.fillText(markZoneWord.str, markZoneWord.x, markZoneWord.y)
        })
      }

      // 绘制黑名单的数据
      if (
        !series.xAxis.markZonesOfBlackListPoints ||
        series.xAxis.markZonesOfBlackListPoints.length === 0
      ) {
        series.xAxis.markZonesOfBlackListWords = []
        series.xAxis.markZonesOfBlackListPointColors = []
        series.xAxis.markZonesOfBlackList.forEach((markZone) => {
          const transformedStartX = markZone.start
          const transformedendX = markZone.end

          const transformedstartY = series.yAxis.interval[0]
          const transformedendY = series.yAxis.interval[1]
          if (markZone.points.length === 0) {
            series.xAxis.markZonesOfBlackListPoints =
              series.xAxis.markZonesOfBlackListPoints.concat([
                transformedStartX,
                transformedstartY,
                transformedendX,
                transformedstartY,
                transformedStartX,
                transformedendY,
                transformedStartX,
                transformedendY,
                transformedendX,
                transformedendY,
                transformedendX,
                transformedstartY
              ])
            markZone.points = [
              transformedStartX,
              transformedstartY,
              transformedendX,
              transformedstartY,
              transformedStartX,
              transformedendY,
              transformedStartX,
              transformedendY,
              transformedendX,
              transformedendY,
              transformedendX,
              transformedstartY
            ]
            series.xAxis.markZonesOfBlackListPointColors =
              series.xAxis.markZonesOfBlackListPointColors.concat([
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a,
                markZone.color.r,
                markZone.color.g,
                markZone.color.b,
                markZone.color.a
              ])
            // 绘制两条有宽度的边框
            if (markZone.borderColor) {
              const width =
                (2 /
                  (_container.clientWidth -
                    series.yAxis.padding -
                    -series.yAxis.defaltPadding)) *
                (series.xAxis.interval[1] - series.xAxis.interval[0])

              series.xAxis.markZonesOfBlackListPoints =
                series.xAxis.markZonesOfBlackListPoints.concat([
                  transformedStartX - width,
                  transformedstartY,
                  transformedStartX,
                  transformedstartY,
                  transformedStartX - width,
                  transformedendY,
                  transformedStartX - width,
                  transformedendY,
                  transformedStartX,
                  transformedendY,
                  transformedStartX,
                  transformedstartY,

                  transformedendX,
                  transformedstartY,
                  transformedendX + width,
                  transformedstartY,
                  transformedendX,
                  transformedendY,
                  transformedendX,
                  transformedendY,
                  transformedendX + width,
                  transformedendY,
                  transformedendX + width,
                  transformedstartY
                ])
              markZone.points = [
                transformedStartX - width,
                transformedstartY,
                transformedStartX,
                transformedstartY,
                transformedStartX - width,
                transformedendY,
                transformedStartX - width,
                transformedendY,
                transformedStartX,
                transformedendY,
                transformedStartX,
                transformedstartY,

                transformedendX,
                transformedstartY,
                transformedendX + width,
                transformedstartY,
                transformedendX,
                transformedendY,
                transformedendX,
                transformedendY,
                transformedendX + width,
                transformedendY,
                transformedendX + width,
                transformedstartY
              ]
              series.xAxis.markZonesOfBlackListPointColors =
                series.xAxis.markZonesOfBlackListPointColors.concat([
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,

                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a,
                  markZone.borderColor.r,
                  markZone.borderColor.g,
                  markZone.borderColor.b,
                  markZone.borderColor.a
                ])
            }
            if (markZone.borderColor) {
            } else {
              // 添加在左右边界添加两条线
              series.xAxis.markZonesOfBlackListLRPoints =
                series.xAxis.markZonesOfBlackListLRPoints.concat([
                  transformedStartX,
                  transformedstartY,
                  transformedStartX,
                  transformedendY,
                  transformedendX,
                  transformedstartY,
                  transformedendX,
                  transformedendY
                ])
            }
            if (markZone.borderColor) {
            } else {
              series.xAxis.markZonesOfBlackListLRPointsColors =
                series.xAxis.markZonesOfBlackListLRPointsColors.concat([
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a,
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a,
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a,
                  markZone.color.r,
                  markZone.color.g,
                  markZone.color.b,
                  markZone.color.a
                ])
            }
          }
          const transformedRealEndX = _getXPixesByXvalueOnLineMatrix(
            markZone.end,
            series
          )
          series.xAxis.markZonesOfBlackListWords.push({
            x: transformedRealEndX + series.yAxis.padding,
            y: series.xAxis.defaltPadding + 15,
            str: markZone.str,
            fillStyle: 'rgb(255,255,255)'
          })
        })
      }
      if (
        series.xAxis.markZonesOfBlackListPoints &&
        series.xAxis.markZonesOfBlackListPoints.length > 0
      ) {
        _drawTranglesWithVaringColor(
          series.xAxis.markZonesOfBlackListPoints,
          series._linesMatrix,
          series.xAxis.markZonesOfBlackListPointColors
        )
        _drawLineGroupWithVaringColor(
          series.xAxis.markZonesOfBlackListLRPoints,
          series._linesMatrix,
          series.xAxis.markZonesOfBlackListLRPointsColors
        )
      }
      // 绘制文字
      series.xAxis.markZonesOfBlackListWords.forEach((markZoneWord) => {
        if (
          markZoneWord.x >
            _container.clientWidth - series.yAxis.defaltPadding ||
          markZoneWord.x < series.yAxis.padding
        ) {
          return
        }
        _textCtx.fillStyle = markZoneWord.fillStyle
        _textCtx.font = '12px sans-serif'
        _textCtx.fillText(markZoneWord.str, markZoneWord.x, markZoneWord.y)
      })
    })
  }

  /**
   * 绘制矩形标记区域
   */
  function _drawRectMarkZone () {
    _Series.forEach((series) => {
      if (
        series.rectMarkZonepoints.length === 0 &&
        series.rectMarkZone.length !== 0
      ) {
        if (!series._linesMatrix) {
          // 根据分辨率直接生成矩阵
          // eslint-disable-next-line no-undef
          let projectionMatrix = m3.projection(
            _gl.canvas.clientWidth -
              series.yAxis.padding -
              series.yAxis.defaltPadding,
            _gl.canvas.clientHeight -
              series.xAxis.padding -
              series.xAxis.defaltPadding
          )
          // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
          const translationMatrix = m3.translation(
            0,
            _gl.canvas.clientHeight -
              series.xAxis.padding -
              series.xAxis.defaltPadding
          )
          projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
          // scaling 绕原点翻转(-1 ~ 1)
          projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
          series._linesMatrix = projectionMatrix
        }
        _gl.useProgram(_lineShaderProgram)
        _gl.viewport(
          series.yAxis.padding,
          series.xAxis.padding,
          _gl.canvas.width - series.yAxis.padding - series.yAxis.defaltPadding,
          _gl.canvas.height - series.xAxis.padding - series.xAxis.defaltPadding
        )

        // 清空文字
        series.markZoneWords = []

        series.rectMarkZone.forEach((markZone) => {
          if (markZone.endY < series.yAxis.interval[0]) {
            // 不在区域内
            return
          }
          const transformedStartX = _getXPixesByXvalueOnLineMatrix(
            markZone.startX,
            series
          )
          const transformedEndX = _getXPixesByXvalueOnLineMatrix(
            markZone.endX,
            series
          )
          const transformedStartY = _getYPixesByYvalueOnLineMatrix(
            markZone.startY,
            series
          )
          const transformedEndY = _getYPixesByYvalueOnLineMatrix(
            markZone.endY,
            series
          )

          const width = 1
          // series.rectMarkZonepoints = series.rectMarkZonepoints.concat([
          //   transformedStartX, transformedStartY + width / 2,
          //   transformedStartX, transformedStartY - width / 2,
          //   transformedendX, transformedStartY + width / 2,
          //   transformedStartX, transformedStartY - width / 2,
          //   transformedendX, transformedStartY + width / 2,
          //   transformedendX, transformedStartY - width / 2,
          //   transformedStartX, transformedEndY + width / 2,
          //   transformedStartX, transformedEndY - width / 2,
          //   transformedendX, transformedEndY + width / 2,
          //   transformedStartX, transformedEndY - width / 2,
          //   transformedendX, transformedEndY + width / 2,
          //   transformedendX, transformedEndY - width / 2,

          //   transformedStartX + width / 2, transformedStartY,
          //   transformedStartX + width / 2, transformedEndY,
          //   transformedStartX - width / 2, transformedStartY,
          //   transformedStartX + width / 2, transformedEndY,
          //   transformedStartX - width / 2, transformedStartY,
          //   transformedStartX - width / 2, transformedEndY,
          //   transformedendX + width / 2, transformedStartY,
          //   transformedendX + width / 2, transformedEndY,
          //   transformedendX - width / 2, transformedStartY,
          //   transformedendX + width / 2, transformedEndY,
          //   transformedendX - width / 2, transformedStartY,
          //   transformedendX - width / 2, transformedEndY
          // ])
          series.rectMarkZonepoints = series.rectMarkZonepoints.concat([
            transformedStartX,
            transformedStartY,
            transformedEndX,
            transformedEndY,
            transformedStartX,
            transformedEndY,

            transformedStartX,
            transformedStartY,
            transformedEndX,
            transformedStartY,
            transformedEndX,
            transformedEndY
          ])
          // series.markZoneWords.push({
          //   x: transformedEndX + series.yAxis.padding,
          //   y: _container.clientHeight - (transformedEndY + series.xAxis.padding) + 10,
          //   str: markZone.str
          // })
        })
      }
      if (series.rectMarkZone.length !== 0) {
        _drawTransparentRect(series.rectMarkZonepoints, series._linesMatrix, {
          r: 1,
          g: 1,
          b: 1
        })
        // _createBuffer(series.rectMarkZonepoints)
        // _gl.useProgram(_lineShaderProgram)
        // _gl.enableVertexAttribArray(_linePositionAttributeLocation)
        // // size=2表示每次迭代读取两个数据，即x和y。由于顶点着色器中gl_Position的类型是vec4，包含x,y,z,w四个数据，而这里只需要前两个x和y。
        // // type=gl_FLOAT表示使用的是32为浮点类型的数据。
        // // normalize=false表示不需要归一化数据。
        // // offset=0表示从缓冲区的开始位置读取数据。
        // _gl.vertexAttribPointer(_linePositionAttributeLocation, 2, _gl.FLOAT, false, 0, 0)

        // // 设置颜色
        // _gl.uniform4f(_lineFragColor, 1, 1, 1, 1)

        // // 设置变换矩阵
        // _gl.uniformMatrix3fv(_linematrixLocation, false, series._linesMatrix)

        // _gl.drawArrays(_gl.TRIANGLES, 0, series.rectMarkZonepoints.length / 2)

        // // 绘制文字
        // series.markZoneWords.forEach((markZoneWord) => {
        //   _textCtx.fillStyle = 'rgb(255,255,255)'
        //   _textCtx.font = '15px sans-serif'
        //   _textCtx.fillText(markZoneWord.str, markZoneWord.x, markZoneWord.y)
        // })
      }
    })
  }

  function _drawImage2D () {
    _Series.forEach((series) => {
      _gl.useProgram(_imageProgram)
      _gl.viewport(
        series.yAxis.padding,
        series.xAxis.padding,
        _container.clientWidth -
          series.yAxis.padding -
          series.yAxis.defaltPadding,
        _container.clientHeight -
          series.xAxis.padding -
          series.xAxis.defaltPadding
      )

      const imageNum = _imageList.length
      // 每张图片所占的宽度
      // const imageWidth = (_gl.canvas.clientWidth -
      //   series.yAxis.padding -
      //   series.yAxis.defaltPadding) / imageNum
      let imageOffset = 0
      _imageList.forEach((image, index) => {
        if (!image._rectinfo) {
          const perc = image.imageColumn / series.column
          const imageWidth =
            perc *
            (_gl.canvas.clientWidth -
              series.yAxis.padding -
              series.yAxis.defaltPadding)
          const rectInfo = {}
          // x轴需要平移的距离 例如 原间距[0,100] 现间距[10,20]
          let xTransfer = 0
          if (
            !series.showAllData &&
            (series.xAxis.interval[0] !== series.xAxis.oldInterval[0] ||
              series.xAxis.interval[1] !== series.xAxis.oldInterval[1])
          ) {
            // x轴缩放了 并且series不一直展示所有数据 对图像进行伸缩
            const percent =
              (series.xAxis.interval[1] - series.xAxis.interval[0]) /
              (series.xAxis.oldInterval[1] - series.xAxis.oldInterval[0])
            // //console.log(percent)
            // 比如x轴缩放了1/10 那么图像的x轴长度要增长10倍
            rectInfo.rectangle = [
              imageOffset,
              0,
              imageWidth / percent,
              _gl.canvas.clientHeight -
                series.xAxis.padding -
                series.xAxis.defaltPadding
            ]
            imageOffset += imageWidth / percent
            // 计算出偏移量
            const tmp =
              ((series.xAxis.interval[0] - series.xAxis.oldInterval[0]) *
                ((_container.clientWidth -
                  series.yAxis.padding -
                  series.yAxis.defaltPadding) /
                  (series.xAxis.oldInterval[1] -
                    series.xAxis.oldInterval[0]))) /
              percent
            xTransfer = tmp
          } else {
            // 没有缩放
            rectInfo.rectangle = [
              imageOffset,
              0,
              imageWidth,
              _gl.canvas.clientHeight -
                series.xAxis.padding -
                series.xAxis.defaltPadding
            ]

            imageOffset += imageWidth
          }
          rectInfo.xTransfer = xTransfer
          series.xTransfer = xTransfer
          image._rectinfo = rectInfo

          _setRectangle(
            _gl,
            image._rectinfo.rectangle[0],
            image._rectinfo.rectangle[1],
            image._rectinfo.rectangle[2],
            image._rectinfo.rectangle[3]
          )
        } else {
          _setRectangle(
            _gl,
            image._rectinfo.rectangle[0],
            image._rectinfo.rectangle[1],
            image._rectinfo.rectangle[2],
            image._rectinfo.rectangle[3]
          )
        }
        // Turn on the position attribute
        _gl.enableVertexAttribArray(_imagePositionAttributeLocation)

        // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
        const size = 2 // 2 components per iteration
        const type = _gl.FLOAT // the data is 32bit floats
        const normalize = false // don't normalize the data
        const stride = 0 // 0 = move forward size * sizeof(type) each iteration to get the next position
        const offset = 0 // start at the beginning of the buffer
        _gl.vertexAttribPointer(
          _imagePositionAttributeLocation,
          size,
          type,
          normalize,
          stride,
          offset
        )

        // provide texture coordinates for the rectangle.
        if (series.direction === 'topToBottom') {
          _createBuffer2([
            0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0
          ])
        } else if (series.direction === 'rightToLeft') {
          _createBuffer2([
            1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0
          ])
        }
        // 向上
        // _createBuffer([
        //   0.0, 1.0,
        //   1.0, 1.0,
        //   0.0, 0.0,
        //   0.0, 0.0,
        //   1.0, 1.0,
        //   1.0, 0.0
        // ])
        // 从左边到右边
        // _createBuffer([
        //   1.0, 0.0,
        //   1.0, 1.0,
        //   0.0, 0.0,
        //   0.0, 0.0,
        //   1.0, 1.0,
        //   0.0, 1.0
        // ])
        // 从右边到左边
        // _createBuffer([
        //   1.0, 1.0,
        //   1.0, 0.0,
        //   0.0, 1.0,
        //   0.0, 1.0,
        //   1.0, 0.0,
        //   0.0, 0.0
        // ])
        _gl.enableVertexAttribArray(_imageTexcoordAttributeLocation)

        _gl.vertexAttribPointer(
          _imageTexcoordAttributeLocation,
          2,
          _gl.FLOAT,
          false,
          0,
          0
        )
        if (!_imgTexure) {
          _imgTexure = _gl.createTexture()
          _gl.bindTexture(_gl.TEXTURE_2D, _imgTexure)

          // Set the parameters so we can render any size image.
          _gl.texParameteri(
            _gl.TEXTURE_2D,
            _gl.TEXTURE_WRAP_S,
            _gl.CLAMP_TO_EDGE
          )
          _gl.texParameteri(
            _gl.TEXTURE_2D,
            _gl.TEXTURE_WRAP_T,
            _gl.CLAMP_TO_EDGE
          )
          // 邻近过滤  GL_NEAREST:OpenGL会选择纹理像素中心点最接近纹理坐标的那个像素
          // 线性过滤 GL_LINEAR:它会基于纹理坐标附近的纹理像素，计算出一个插值，近似出这些纹理像素之间的颜色。
          _gl.texParameteri(
            _gl.TEXTURE_2D,
            _gl.TEXTURE_MIN_FILTER,
            // _gl.NEAREST
            _gl.LINEAR
          )
          _gl.texParameteri(
            _gl.TEXTURE_2D,
            _gl.TEXTURE_MAG_FILTER,
            // _gl.NEAREST
            _gl.LINEAR
          )
        }
        // 获取最大纹理尺寸
        // console.log('最大纹理尺寸:', _gl.getParameter(_gl.MAX_TEXTURE_SIZE)) // 纹理的最大宽度或最大高度
        // Upload the image into the texture.
        // 将数据加载到纹理对象中
        _gl.texImage2D(
          _gl.TEXTURE_2D, // 目标纹理，可以是 gl.TEXTURE_2D 或 gl.TEXTURE_CUBE_MAP
          0, // 纹理级别，0表示基本级别
          _gl.RGBA, // 纹理的内部格式
          image.imageColumn, // 纹理的宽度
          series.row, // 纹理的高度
          0, // 边框大小，必须为0或1
          _gl.RGBA, // 纹理的像素数据格式 gl.RGBA 或 gl.RGB
          _gl.UNSIGNED_BYTE, // 数据类型
          image.imageDataUnit8 // 包含纹理像素数据的 ArrayBufferView 或 ImageData 对象
        )

        if (!series._projectionMatrix) {
          series._projectionMatrix = m3.projection(
            _gl.canvas.clientWidth -
              series.yAxis.padding -
              series.yAxis.defaltPadding,
            _gl.canvas.clientHeight -
              series.xAxis.padding -
              series.xAxis.defaltPadding
          )
          // x轴平移 - xTransfer 保持图像最左边的点坐标正好是x轴最小值的位置
          const translationMatrix = m3.translation(-series.xTransfer, 0)
          series._projectionMatrix = m3.multiply(
            series._projectionMatrix,
            translationMatrix
          )
          // // scaling 绕原点翻转(-1 ~ 1)
          // projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
          // //console.log(projectionMatrix)
          // _axisMatrix = projectionMatrix
          // projectionMatrix = m3.multiply(projectionMatrix, m3.translation(_Series[0].yAxis.padding, _Series[0].xAxis.defaltPadding))
        }
        _gl.uniformMatrix3fv(
          _imageMatrixLocation,
          false,
          series._projectionMatrix
        )

        _gl.drawArrays(_gl.TRIANGLES, 0, 6)
      })
    })
  }

  /**
   * 绘制瀑布图当前使用的色带
   */
  function _drawWaterColors () {
    _Series.forEach((series) => {
      if (!series.showColors) {
        return
      }
      const num = 1
      const padding = 5
      const startY = series.xAxis.padding
      const endY = _container.clientHeight - series.xAxis.defaltPadding

      const startX =
        _container.clientWidth - series.yAxis.defaltPadding + padding
      const endX = _container.clientWidth - padding
      // 遍历色带
      if (series.waterColors && series.waterColors.length > 0) {
        const oneHeight = (endY - startY) / series.waterColors.length
        const startPosition = startY

        let points = []
        let colors = []
        for (let i = 0; i < series.waterColors.length; i++) {
          points = points.concat([
            startX,
            startPosition + i * oneHeight,
            endX,
            startPosition + i * oneHeight + oneHeight,
            startX,
            startPosition + i * oneHeight + oneHeight,
            startX,
            startPosition + i * oneHeight,
            endX,
            startPosition + i * oneHeight + oneHeight,
            endX,
            startPosition + i * oneHeight
          ])
          const color = series.waterColors[i]
          colors = colors.concat([
            color.R / 255,
            color.G / 255,
            color.B / 255,
            1,
            color.R / 255,
            color.G / 255,
            color.B / 255,
            1,
            color.R / 255,
            color.G / 255,
            color.B / 255,
            1,
            color.R / 255,
            color.G / 255,
            color.B / 255,
            1,
            color.R / 255,
            color.G / 255,
            color.B / 255,
            1,
            color.R / 255,
            color.G / 255,
            color.B / 255,
            1
          ])
        }
        _drawTranglesWithVaringColor(points, _axisMatrix, colors)
      }
      // let points = [
      //   startX,startY,
      //   endX,endY,
      //   startX,endY,
      //   startX,startY,
      //   endX,endY,
      //   endX,startY
      // ]
      // let colors = [
      //   0,255,255,1,
      //   0,255,255,1,
      //   0,255,255,1,
      //   0,255,255,1,
      //   0,255,255,1,
      //   0,255,255,1,
      // ]
      // _drawTranglesWithVaringColor(points,_axisMatrix,colors)
    })
  }

  /**
   * 绘制x轴测量的标记
   */
  function _drawMeasure () {
    _Series.forEach((series) => {
      _gl.useProgram(_lineShaderProgram)

      _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
      if (series.SNRMeasureOpen) {
        if (series.SNRMeasure) {
        } else {
          // 设置到屏幕中间
          series.SNRMeasure = {
            type: 'SNR',
            startX:
              (_container.clientWidth -
                series.yAxis.padding -
                series.yAxis.defaltPadding) /
                2 -
              100 +
              series.yAxis.padding,
            endX:
              (_container.clientWidth -
                series.yAxis.padding -
                series.yAxis.defaltPadding) /
                2 +
              100 +
              series.yAxis.padding,
            startY:
              (_container.clientHeight -
                series.xAxis.padding -
                series.xAxis.defaltPadding) /
                2 -
              50 +
              series.xAxis.padding,
            endY:
              (_container.clientHeight -
                series.xAxis.padding -
                series.xAxis.defaltPadding) /
                2 +
              50 +
              series.xAxis.padding,
            points: [],
            words: []
          }
        }
        if (
          !series.SNRMeasure.points ||
          series.SNRMeasure.points.length === 0
        ) {
          const points = [
            series.SNRMeasure.startX,
            series.SNRMeasure.startY,
            series.SNRMeasure.startX,
            series.SNRMeasure.endY,
            series.SNRMeasure.endX,
            series.SNRMeasure.endY,

            series.SNRMeasure.endX,
            series.SNRMeasure.endY,
            series.SNRMeasure.startX,
            series.SNRMeasure.startY,
            series.SNRMeasure.endX,
            series.SNRMeasure.startY
          ]
          series.SNRMeasure.points = points
        }
        _drawTransparentRect(series.SNRMeasure.points, _axisMatrix, {
          r: 0,
          g: 1,
          b: 1
        })
        if (!series.SNRMeasure.words || series.SNRMeasure.words.length === 0) {
          const realStartYValue = _getRealYValueByYPixes(
            series.SNRMeasure.startY,
            series
          )
          const realEndYValue = _getRealYValueByYPixes(
            series.SNRMeasure.endY,
            series
          )
          series.SNRMeasure.words = [
            {
              x: series.SNRMeasure.endX,
              y: _container.clientHeight - series.SNRMeasure.startY,
              str: series.yAxis.yAxisMarkFormatter
                ? series.yAxis.yAxisMarkFormatter(realStartYValue.toFixed(2))
                : realStartYValue.toFixed(2).toString()
            },
            {
              x: series.SNRMeasure.endX,
              y: _container.clientHeight - series.SNRMeasure.endY,
              str: series.yAxis.yAxisMarkFormatter
                ? series.yAxis.yAxisMarkFormatter(realEndYValue.toFixed(2))
                : realEndYValue.toFixed(2).toString()
            }
          ]
        }
        series.SNRMeasure.words.forEach((word) => {
          _textCtx.fillStyle =
            'rgba(' +
            255 * series.measureTextColor.r +
            ',' +
            255 * series.measureTextColor.g +
            ',' +
            255 * series.measureTextColor.b +
            ',' +
            255 * series.measureTextColor.a +
            ')'
          _textCtx.font = '15px sans-serif'
          _textCtx.fillText(word.str, word.x, word.y)
        })
      }
      if (series.freqMeasureOpen) {
        if (series.freqMeasure) {
        } else {
          // 设置到屏幕中间
          series.freqMeasure = {
            type: 'freq',
            startX:
              (_container.clientWidth -
                series.yAxis.padding -
                series.yAxis.defaltPadding) /
                2 -
              100 +
              series.yAxis.padding,
            endX:
              (_container.clientWidth -
                series.yAxis.padding -
                series.yAxis.defaltPadding) /
                2 +
              100 +
              series.yAxis.padding,
            startY: series.xAxis.padding,
            endY: _container.clientHeight - series.xAxis.defaltPadding,
            points: [],
            words: []
          }
        }
        if (
          !series.freqMeasure.points ||
          series.freqMeasure.points.length === 0
        ) {
          const points = [
            series.freqMeasure.startX,
            series.freqMeasure.startY,
            series.freqMeasure.startX,
            series.freqMeasure.endY,
            series.freqMeasure.endX,
            series.freqMeasure.endY,

            series.freqMeasure.endX,
            series.freqMeasure.endY,
            series.freqMeasure.startX,
            series.freqMeasure.startY,
            series.freqMeasure.endX,
            series.freqMeasure.startY
          ]
          series.freqMeasure.points = points
        }
        _drawTransparentRect(series.freqMeasure.points, _axisMatrix, {
          r: 0,
          g: 1,
          b: 1
        })
        if (
          !series.freqMeasure.words ||
          series.freqMeasure.words.length === 0
        ) {
          const realStartXValue = _getRealXValueByXPixes(
            series.freqMeasure.startX,
            series
          )
          const realEndXValue = _getRealXValueByXPixes(
            series.freqMeasure.endX,
            series
          )
          series.freqMeasure.words = [
            {
              x: series.freqMeasure.startX,
              y: _container.clientHeight / 2,
              str: series.xAxis.xAxisMarkFormatter
                ? series.xAxis.xAxisMarkFormatter(realStartXValue.toFixed(2))
                : realStartXValue.toFixed(2).toString()
            },
            {
              x: series.freqMeasure.endX,
              y: _container.clientHeight / 2,
              str: series.xAxis.xAxisMarkFormatter
                ? series.xAxis.xAxisMarkFormatter(realEndXValue.toFixed(2))
                : realEndXValue.toFixed(2).toString()
            }
          ]
        }
        series.freqMeasure.words.forEach((word) => {
          _textCtx.fillStyle =
            'rgba(' +
            255 * series.measureTextColor.r +
            ',' +
            255 * series.measureTextColor.g +
            ',' +
            255 * series.measureTextColor.b +
            ',' +
            255 * series.measureTextColor.a +
            ')'
          _textCtx.font = '15px sans-serif'
          _textCtx.fillText(word.str, word.x, word.y)
        })
      }
      if (series.kdCollectionOpen) {
        if (series.kdCollection) {
          // if(!series.kdCollection.points || series.kdCollection.points.length === 0){
          //   let kdCollectionPositionValue = series.kdCollection.kdCollectionPositionValue
          //   let kdCollectionPosition = _getXPixesByXvalue(kdCollectionPositionValue,series)
          //   //console.log("kdCollectionPosition:"+kdCollectionPosition)
          //   let collectonZoneWidth = (series.kdCollectionWidth/(series.xAxis.interval[1] - series.xAxis.interval[0])) * (_container.clientWidth - series.yAxis.padding  - series.yAxis.defaltPadding)
          //   series.kdCollection.startX = kdCollectionPosition - collectonZoneWidth/2 + series.yAxis.padding
          //   series.kdCollection.endX = kdCollectionPosition + collectonZoneWidth/2 + series.yAxis.padding
          //   series.kdCollection.startY = series.xAxis.padding
          //   series.kdCollection.endY = _container.clientHeight  - series.xAxis.defaltPadding
          //   //console.log("kdCollectionPositionValue:"+kdCollectionPositionValue)
          // }
        } else {
          // todo 可设置初始位置
          // 设置到屏幕中间
          const kdCollectionPosition =
            series.yAxis.padding +
            (_container.clientWidth -
              series.yAxis.padding -
              series.yAxis.defaltPadding) /
              2
          const kdCollectionPositionValue = _getRealXValueByXPixes(
            kdCollectionPosition,
            series
          )
          // //console.log("kdCollectionPositionValue:" +kdCollectionPositionValue)
          const collectonZoneWidth =
            (series.kdCollectionWidth /
              (series.xAxis.interval[1] - series.xAxis.interval[0])) *
            (_container.clientWidth -
              series.yAxis.padding -
              series.yAxis.defaltPadding)
          series.kdCollection = {
            type: 'kdCollection',
            kdCollectionPosition: kdCollectionPosition,
            kdCollectionPositionValue: kdCollectionPositionValue,
            collectonZoneWidth: collectonZoneWidth,
            startX: kdCollectionPosition - collectonZoneWidth / 2,
            endX: kdCollectionPosition + collectonZoneWidth / 2,
            startY: series.xAxis.padding,
            endY: _container.clientHeight - series.xAxis.defaltPadding,
            points: [],
            words: []
          }
        }
        if (
          !series.kdCollection.points ||
          series.kdCollection.points.length === 0
        ) {
          const points = [
            series.kdCollection.startX,
            series.kdCollection.startY,
            series.kdCollection.startX,
            series.kdCollection.endY,
            series.kdCollection.endX,
            series.kdCollection.endY,

            series.kdCollection.endX,
            series.kdCollection.endY,
            series.kdCollection.startX,
            series.kdCollection.startY,
            series.kdCollection.endX,
            series.kdCollection.startY
          ]
          series.kdCollection.points = points
          const s =
            '中心频率:' +
            (series.kdCollection.kdCollectionPositionValue / 1000000).toFixed(
              2
            ) +
            'MHz,带宽：' +
            series.kdCollectionWidth / 1000000 +
            'MHz'
          _textCtx.font = '13px sans-serif'
          series.kdCollectionword = {
            str: s,
            x:
              series.yAxis.padding +
              series.kdCollection.kdCollectionPosition -
              _textCtx.measureText(s).width / 2,
            y: _container.clientHeight / 2
          }
        }

        _drawTransparentRect(series.kdCollection.points, _axisMatrix, {
          r: 0,
          g: 1,
          b: 1
        })
        if (series.kdCollectionword) {
          _textCtx.fillStyle =
            'rgba(' +
            255 * series.measureTextColor.r +
            ',' +
            255 * series.measureTextColor.g +
            ',' +
            255 * series.measureTextColor.b +
            ',' +
            255 * series.measureTextColor.a +
            ')'
          _textCtx.font = '13px sans-serif'
          _textCtx.fillText(
            series.kdCollectionword.str,
            series.kdCollectionword.x,
            series.kdCollectionword.y
          )
        }
      }
    })
  }

  /**
   * 绘制时间测量标记
   */
  function _drawTimeMeasure () {
    _Series.forEach((series) => {
      _gl.useProgram(_lineShaderProgram)
      _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
      if (series.timeMeasureOpen && series.timeMeasure) {
        if (
          !series.timeMeasure.points ||
          series.timeMeasure.points.length === 0
        ) {
          const points = [
            series.timeMeasure.startX,
            series.timeMeasure.startY,
            series.timeMeasure.startX,
            series.timeMeasure.endY,
            series.timeMeasure.endX,
            series.timeMeasure.endY,

            series.timeMeasure.endX,
            series.timeMeasure.endY,
            series.timeMeasure.startX,
            series.timeMeasure.startY,
            series.timeMeasure.endX,
            series.timeMeasure.startY
          ]
          series.timeMeasure.points = points
        }
        _drawTransparentRect(series.timeMeasure.points, _axisMatrix, {
          r: 0,
          g: 1,
          b: 1
        })
        if (
          !series.timeMeasure.words ||
          series.timeMeasure.words.length === 0
        ) {
          const realStartY = _getRealYValueByYPixes(
            series.timeMeasure.startY,
            series
          )
          const realEndY = _getRealYValueByYPixes(
            series.timeMeasure.endY,
            series
          )
          // 需要将realX转化成真实时间戳
          const startidx = series.yAxis.interval[1] - realStartY
          const realstartYValue =
            series.yAxis.timeStamps[
              series.yAxis.timeStamps.length - 1 - Math.round(startidx)
            ]

          const endidx = series.yAxis.interval[1] - realEndY
          const realEndYValue =
            series.yAxis.timeStamps[
              series.yAxis.timeStamps.length - 1 - Math.round(endidx)
            ]
          _textCtx.fillStyle = 'rgba(0,255,255,0.5)'
          _textCtx.font = '15px sans-serif'
          series.timeMeasure.words = [
            {
              x:
                series.timeMeasure.startX -
                _textCtx.measureText(getHHmmssSSS(realstartYValue)).width,
              y: _container.clientHeight - series.timeMeasure.startY + 10,
              str: getHHmmssSSS(realstartYValue)
            },
            {
              x:
                series.timeMeasure.startX -
                _textCtx.measureText(getHHmmssSSS(realEndYValue)).width,
              y: _container.clientHeight - series.timeMeasure.endY,
              str: getHHmmssSSS(realEndYValue)
            }
          ]
        }
        series.timeMeasure.words.forEach((word) => {
          _textCtx.fillStyle =
            'rgba(' +
            255 * series.measureTextColor.r +
            ',' +
            255 * series.measureTextColor.g +
            ',' +
            255 * series.measureTextColor.b +
            ',' +
            255 * series.measureTextColor.a +
            ')'
          _textCtx.font = '15px sans-serif'
          _textCtx.fillText(word.str, word.x, word.y)
        })
      }
    })
  }

  /**
   * 绘制鼠标点击标记
   */
  function _drawMouseClickMarkPoints () {
    // 设置使用的着色器和viewport
    _gl.useProgram(_lineShaderProgram)
    _gl.viewport(0, 0, _gl.canvas.width, _gl.canvas.height)
    if (!_axisMatrix) {
      // 计算矩阵
      // 根据分辨率直接生成矩阵
      let projectionMatrix = m3.projection(
        _gl.canvas.clientWidth,
        _gl.canvas.clientHeight
      )
      // 因为上面的方法生成的矩阵原点在左上方 需要原点在左下方,所以先沿y轴平移canvas高度(向上),在沿y轴翻转 (这样原点的坐标就在左下了)
      const translationMatrix = m3.translation(0, _gl.canvas.clientHeight)
      projectionMatrix = m3.multiply(projectionMatrix, translationMatrix)
      // scaling 绕原点翻转(-1 ~ 1)
      projectionMatrix = m3.multiply(projectionMatrix, m3.scaling(1, -1))
      _axisMatrix = projectionMatrix
    }
    _Series.forEach((series, index) => {
      // 设置使用的着色器和viewport
      if (
        series.mouseClickMarkPoints &&
        series.mouseClickMarkPoints.length > 0
      ) {
        // 暂时不需要绘制绿色点击的条了
        // _drawLineGroup(series.mouseClickMarkPoints, _axisMatrix, { r: 0, g: 200 / 255, b: 0 })
      }
    })
  }

  /**
   * 清空所有计算过的点坐标数据(需要重新计算)
   */
  function _clearCaculatedData () {
    _Series.forEach((series) => {
      // xAxis 重新计算
      series.xAxis.points = []
      // yAxis 重新计算
      series.yAxis.points = []
      // 表格线清空
      series.yTablePoints = []
      series.xTablePoints = []

      series.xAxis.markZonePoints = []
      series.xAxis.markZonePointColors = []
      series.xAxis.markZoneLRPoints = []
      series.xAxis.markZoneLRPointsColors = []

      series.xAxis.markZonesOfBlackListPoints = []
      series.xAxis.markZonesOfBlackListPointColors = []
      series.xAxis.markZonesOfBlackListLRPoints = []
      series.xAxis.markZonesOfBlackListLRPointsColors = []

      // 重新计算宽带采集图像坐标
      // series.kdCollection = null
      // 重新计算绘制折线的变换矩阵
      series._linesMatrix = null
      series.lines.forEach((line) => {
        line.transferedData = []
      })
      series.xAxis.markLines.forEach((markLine) => {
        markLine.points = []
      })
      series.yAxis.markLines.forEach((markLine) => {
        markLine.points = []
      })
      series.xAxis.markZones.forEach((markZone) => {
        markZone.points = []
      })
      series.xAxis.markZonesOfBlackList.forEach((markZone) => {
        markZone.points = []
      })
      series.xAxis.markZonesHighLight.forEach((markZoneHighLight) => {
        markZoneHighLight.points = []
      })

      if (_config.type === 'pubu') {
        series._projectionMatrix = null
        _imageList.forEach((image) => {
          image._rectinfo = null
        })
        series.rectMarkZonepoints = []
        // series.rectMarkZone.forEach((markZone) => {
        //   // markZone.transformedData = []
        // })
      }
    })
  }

  /**
   * 绘制图案的矩形的坐标生成
   */
  function _setRectangle (gl, x, y, width, height) {
    const x1 = x
    const x2 = x + width
    const y1 = y
    const y2 = y + height
    // _createBuffer([
    //   0.0, 0.0,
    //   1.0, 0.0,
    //   0.0, 1.0,
    //   0.0, 1.0,
    //   1.0, 0.0,
    //   1.0, 1.0
    // ])
    // (0,0)<------------(0,1)
    //   |               x/^
    //   |              // |
    //   |             //  |
    //   |            //   |
    //   |           //    |
    //   |          //     |
    //   |         //      |
    //   |        //       |
    //   |       //        |
    //   |      //         |
    //   |     //          |
    //   |    //           |
    //   |   //            |
    //   x  x              |
    // (1,0)------------->(1,1)
    _createBuffer([
      x1,
      y1, // 0,0,
      x2,
      y1, // 1,0
      x1,
      y2, // 0,1
      x1,
      y2, // 0,1
      x2,
      y1, // 1,0
      x2,
      y2 // 1,1
    ])
    // 向上
    // _createBuffer([
    //   x1,y2,// 0,1
    //   x2,y2,// 1,1
    //   x1,y1,// 0,0,

    //   x1, y1, // 0,1
    //   x2, y1, // 1,0
    //   x2, y2,  // 1,0
    // ])
    // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    //   x1, y1, // 0,0,
    //   x2, y1, // 1,0
    //   x1, y2, // 0,1
    //   x1, y2, // 0,1
    //   x2, y1, // 1,0
    //   x2, y2  // 1,1
    // ]), gl.STATIC_DRAW)
  }

  /**
   * 添加罗盘鼠标事件监听
   */
  function _addCompassMouseEventListener () {
    _textcontainer.onmousedown = (event) => {
      const x = event.offsetX - _container.clientWidth / 2
      const y = -event.offsetY + _container.clientHeight / 2
      _isMouseDown = true
      _mouseDownStart = {
        x: x,
        y: y
      }
    }
    _textcontainer.onmouseleave = (event) => {
      // //console.log('onmouseleave')
      if (_isMouseDown) {
        _isMouseDown = false
        _compassConfig.preJiaotdu = null
        // _isClickCompassPoint = false

        _compassConfig.totalJiaoDuChange = 0
        // let change = (_compassPointRotation - _compassPointOldRotation) * 180 / Math.PI
        _compassConfig.compassPointRotation =
          _compassConfig.compassPointOldRotation
        _compassConfig.sectorPoints = []
        _refresh()
      }
    }
    _textcontainer.onmousemove = (event) => {
      const x = event.offsetX - _container.clientWidth / 2
      const y = -event.offsetY + _container.clientHeight / 2
      // 判断是否点击到了指针位置
      // if (!_isClickCompassPoint) {
      //   if (_isCursorInCompassPoints(x, y)) {
      //     _textcontainer.style.cursor = 'all-scroll'
      //   } else {
      //     _textcontainer.style.cursor = ''
      //   }
      //   return
      // }
      if (_isMouseDown) {
        const jiaodutmp = Math.atan2(x, y)
        let jiaodu = jiaodutmp
        if (jiaodutmp < 0) {
          jiaodu = 2 * Math.PI + jiaodu
        }
        // //console.log(jiaodu)
        const pointRotationLast = jiaodu
        // 计算和之前角度的角度差值
        let jiaoduChange = 0
        if (_compassConfig.preJiaotdu != null) {
          jiaoduChange = jiaodu - _compassConfig.preJiaotdu
          // //console.log("preJiaotdu" +  _compassConfig.preJiaotdu)
          // //console.log("jiaoduChange" + jiaoduChange)
          if (Math.abs(jiaoduChange) > Math.PI) {
            // 可能是经过了y轴
            if (_compassConfig.preJiaotdu > jiaodu) {
              // //console.log("从左到右")
              // 从左到右
              jiaoduChange = 2 * Math.PI - _compassConfig.preJiaotdu + jiaodu
            } else {
              // //console.log("从右到左")
              // 从右到左
              jiaoduChange = -(
                2 * Math.PI -
                jiaodu +
                _compassConfig.preJiaotdu
              )
            }
          }
          // if (Math.abs(jiaoduChange * 180 / Math.PI) > 100) {
          //   //console.log('jiaoduChange:' + (jiaoduChange * 180 / Math.PI))
          // }
          // //console.log('jiaoduChange:' + (jiaoduChange * 180 / Math.PI))
          _compassConfig.preJiaotdu = jiaodu
        } else {
          // debugger
          jiaoduChange =
            jiaodu - getRotationByPoints(_mouseDownStart.x, _mouseDownStart.y)
          if (Math.abs(jiaoduChange) > Math.PI) {
            // 可能是经过了y轴 此时没有上一次所在的角度 直接比较点击开始位置的坐标x和当前坐标x的大小
            if (x > _mouseDownStart.x) {
              // //console.log("1从左到右")
              // 从左到右
              jiaoduChange =
                2 * Math.PI -
                getRotationByPoints(_mouseDownStart.x, _mouseDownStart.y) +
                jiaodu
            } else {
              // //console.log("1从右到左")
              // 从右到左
              jiaoduChange = -(
                2 * Math.PI -
                jiaodu +
                getRotationByPoints(_mouseDownStart.x, _mouseDownStart.y)
              )
            }
          }
          _compassConfig.preJiaotdu = jiaodu
        }
        _compassConfig.totalJiaoDuChange += jiaoduChange

        if (Math.abs(_compassConfig.totalJiaoDuChange) > 2 * Math.PI) {
          if (_compassConfig.totalJiaoDuChange > 0) {
            _compassConfig.totalJiaoDuChange = 2 * Math.PI
          } else {
            _compassConfig.totalJiaoDuChange = -2 * Math.PI
          }
        }
        // //console.log("totalJiaoDuChange:" +_compassConfig.totalJiaoDuChange )
        // 绘制扇形区域
        const startRotation = getRotationByPoints(
          _mouseDownStart.x,
          _mouseDownStart.y
        )

        _compassConfig.startRotation = startRotation
        // let stopRotation = startRotation + _compassConfig.totalJiaoDuChange
        const stopRotation = getRotationByPoints(x, y)
        _compassConfig.stopRotation = stopRotation
        _compassConfig.pointShowJiaoDuChange = _compassConfig.totalJiaoDuChange
        let points = []
        points = points.concat([0, 0])
        let n =
          Math.abs(
            ((_compassConfig.totalJiaoDuChange * 180) / Math.PI / 10).toFixed(0)
          ) * 5
        if (n === 0) {
          n = 10
        }
        const banjing = _container.clientHeight / 2 - 5
        const startTheta = startRotation
        for (let i = 0; i < n + 1; i++) {
          const theta = startTheta + (i * _compassConfig.totalJiaoDuChange) / n
          const x1 = 0 + banjing * Math.sin(theta)
          const y1 = 0 + banjing * Math.cos(theta)
          points = points.concat([x1, y1])
        }
        _compassConfig.sectorPoints = points

        _refresh()
        // _drawTransparentTrangleFan([0, 0, 0, 150, 1, 140], _compassPointMatrix, {r: 1, g: 1, b: 1})
      }
    }
    _textcontainer.onmouseup = (event) => {
      if (_isMouseDown) {
        _isMouseDown = false
        _compassConfig.preJiaotdu = null
        // _isClickCompassPoint = false
        // //console.log(_compassConfig.totalJiaoDuChange * 180 / Math.PI)
        if (_compassConfig.compassMeasureListener) {
          _compassConfig.compassMeasureListener(
            (_compassConfig.totalJiaoDuChange * 180) / Math.PI
          )
        }
        _compassConfig.totalJiaoDuChange = 0
        // let change = (_compassPointRotation - _compassPointOldRotation) * 180 / Math.PI
        _compassConfig.compassPointRotation =
          _compassConfig.compassPointOldRotation
        _compassConfig.sectorPoints = []

        _compassConfig.comapssShowPoints = []
        _compassConfig.compassShowPointSizes = []
        _refresh()
      }
    }
  }

  /**
   * 根据xy坐标计算角度(0~2π)
   */
  function getRotationByPoints (x, y) {
    let jiaodutmp = Math.atan2(x, y)
    if (jiaodutmp < 0) {
      jiaodutmp = 2 * Math.PI + jiaodutmp
    }
    return jiaodutmp
  }

  /**
   * 判断鼠标指针是否在罗盘指针上
   */
  function _isCursorInCompassPoints (x, y) {
    const points = [
      { x: _container.clientHeight / 60, y: _container.clientHeight / 2 - 10 },
      { x: -_container.clientHeight / 60, y: _container.clientHeight / 2 - 10 },

      { x: _container.clientHeight / 60, y: _container.clientHeight / 60 },
      { x: 0, y: -_container.clientHeight / 60 },
      { x: -_container.clientHeight / 60, y: _container.clientHeight / 60 },
      { x: 0, y: _container.clientHeight / 2 - 10 }
    ]
    // 所有的点需要旋转当前的指针的角度
    const matrix = m3.rotation(_compassConfig.compassPointRotation, [])
    const transformedPoints = []
    for (let i = 0; i < points.length; i++) {
      const point = points[i]
      const tmp = m3.transformPoint(matrix, [point.x, point.y])
      transformedPoints.push({
        x: tmp[0],
        y: tmp[1]
      })
    }
    const isIn = _pointInPolygon({ x, y }, transformedPoints, 5)
    return isIn
  }

  /**
   * 判断点是否在多边形内部
   * 注意到如果从P作水平向左的射线的话，如果P在多边形内部，那么这条射线与多边形的交点必为奇数，如果P在多边形外部，则交点个数必为偶数（0也在内）。所以，我们可以顺序考虑多边形的每条边，求出交点的总个数。还有一些特殊情况要考虑。假如考虑边(P1,P2)，
   *   1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次，处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同，则直接忽略这种情况
   *   2)如果射线水平，则射线要么与其无交点，要么有无数个，这种情况也直接忽略。
   *   3)如果射线竖直，而P0的横坐标小于P1,P2的横坐标，则必然相交。
   *   4)再判断相交之前，先判断P是否在边(P1,P2)的上面，如果在，则直接得出结论：P再多边形内部。
   * 求解通过该点的水平线与多边形各边的交点
   * 单边交点为奇数，成立
   */
  function _pointInPolygon (point, ptPolygon, nCount) {
    let nCross = 0
    for (let i = 0; i < nCount; i++) {
      const p1 = ptPolygon[i]
      const p2 = ptPolygon[(i + 1) % nCount]
      // 求解 y=p.y 与 p1p2 的交点
      if (p1.y === p2.y) {
        continue
      }
      if (point.y < Math.min(p1.y, p2.y)) {
        continue
      }
      if (point.y >= Math.max(p1.y, p2.y)) {
        continue
      }
      // 求交点的 X 坐标 --------------------------------------------------------------
      const x = ((point.y - p1.y) * (p2.x - p1.x)) / (p2.y - p1.y) + p1.x
      if (x > point.x) {
        nCross++
      }
    }
    // 单边交点为偶数，点在多边形之外 ---
    return nCross % 2 === 1
  }

  /**
   * 添加鼠标事件监听
   */
  function _addMouseEventListener () {
    _textcontainer.onmouseleave = () => {
      _isMouseDown = false
      _mouseDownStart = {}
      _lastMousePosition = null
      _mouseMovePre = null
      // 清空拉出来的矩形
      _Series.forEach((series) => {
        series.mouseStrapPoints = []
      })

      if (_isClickXaxisPadding) {
        _isClickXaxisPadding = false
        // 调用onchange
        // if (_clickedXaxisSeries.xAxis.onXIntervalChange) {
        //   _clickedXaxisSeries.xAxis.onXIntervalChange([_clickedXaxisSeries.xAxis.interval[0], _clickedXaxisSeries.xAxis.interval[1]])
        // }
      }
      _refresh()
    }
    _textcontainer.onmousewheel = (event) => {
      event.stopPropagation()
      event.preventDefault()
      if (!_isMouseDown) {
        // 缩放图表
        const x = event.offsetX
        const y = event.offsetY
        _Series.forEach((series, index) => {
          if (!series.allowZoom) {
            // 禁止了缩放
            return
          }
          // 判断滚动区域是否在Axies图表内部
          // if (x < series.yAxis.padding) {
          //   return
          // }
          // if (x > (_container.clientWidth - series.yAxis.defaltPadding)) {
          //   return
          // }
          if (
            x <= _container.clientWidth - series.yAxis.defaltPadding &&
            x >= series.yAxis.padding
          ) {
            if (event.deltaY < 0) {
              // 往上方滚动 放大
              if (series.xAxis.minXInterval) {
                if (
                  series.xAxis.interval[1] - series.xAxis.interval[0] <=
                  series.xAxis.minXInterval
                ) {
                  // 已经到达最小间隔
                  return
                }
              }
              const realX = _getRealXValueByXPixes(x, series)
              // 鼠标左右分别变成以前的 90%
              let nextLeft = realX - (realX - series.xAxis.interval[0]) * 0.9
              let nextRight = realX + (series.xAxis.interval[1] - realX) * 0.9
              if (series.xAxis.minXInterval) {
                // 判断改变过后的x最大值和最小值的间隔是否小于最小x间隔
                if (nextRight - nextLeft < series.xAxis.minXInterval) {
                  nextRight = nextLeft + series.xAxis.minXInterval
                  if (nextRight > series.xAxis.oldInterval[1]) {
                    nextRight = series.xAxis.oldInterval[1]
                    nextLeft = nextRight - series.xAxis.minXInterval
                  }
                }
              }
              // 重新设置
              series.xAxis.interval[0] = nextLeft
              series.xAxis.interval[1] = nextRight
              _clearCaculatedData()
              _refresh()
              // 调用onchange
              // if (series.xAxis.onXIntervalChange) {
              _doOnXIntervalChange(series, [nextLeft, nextRight])
              // }
            }
            if (event.deltaY > 0) {
              // 往下方滚动 缩小
              const realX = _getRealXValueByXPixes(x, series)
              let newLeft = realX - (realX - series.xAxis.interval[0]) * 1.1
              let newRight = realX + (series.xAxis.interval[1] - realX) * 1.1
              if (newLeft < series.xAxis.oldInterval[0]) {
                newLeft = series.xAxis.oldInterval[0]
              }
              if (newRight > series.xAxis.oldInterval[1]) {
                newRight = series.xAxis.oldInterval[1]
              }
              series.xAxis.interval[0] = newLeft
              series.xAxis.interval[1] = newRight
              _clearCaculatedData()
              _refresh()
              // 调用onchange
              // if (series.xAxis.onXIntervalChange) {
              _doOnXIntervalChange(series, [newLeft, newRight])
              // }
            }
          }
          if (x < series.yAxis.padding) {
            if (_config.type !== 'line') {
              // 只有线图才能放大y轴
              return
            }
            if (event.deltaY < 0) {
              // 往上方滚动 放大
              if (series.yAxis.minXInterval) {
                if (
                  series.yAxis.interval[1] - series.yAxis.interval[0] <=
                  series.yAxis.minXInterval
                ) {
                  // 已经到达最小间隔
                  return
                }
              }
              const realY = _getRealYValueByYPixes(
                _container.clientHeight - y,
                series
              )
              // 鼠标左右分别变成以前的 90%
              let nextLeft = realY - (realY - series.yAxis.interval[0]) * 0.9
              let nextRight = realY + (series.yAxis.interval[1] - realY) * 0.9
              if (series.yAxis.minXInterval) {
                // 判断改变过后的x最大值和最小值的间隔是否小于最小x间隔
                if (nextRight - nextLeft < series.yAxis.minXInterval) {
                  nextRight = nextLeft + series.yAxis.minXInterval
                  if (nextRight > series.yAxis.oldInterval[1]) {
                    nextRight = series.yAxis.oldInterval[1]
                    nextLeft = nextRight - series.yAxis.minXInterval
                  }
                }
              }
              // 重新设置
              series.yAxis.interval[0] = nextLeft
              series.yAxis.interval[1] = nextRight
              // if (true) {
              //   // 根据范围内的y轴数值动态修改y轴的interval
              //   autoResize(series)
              // }
              _clearCaculatedData()
              _refresh()
              // 调用onchange
              if (series.yAxis.onYIntervalChange) {
                series.yAxis.onYIntervalChange([nextLeft, nextRight])
              }
            }
            if (event.deltaY > 0) {
              // 往下方滚动 缩小
              const realY = _getRealYValueByYPixes(
                _container.clientHeight - y,
                series
              )
              let newLeft = realY - (realY - series.yAxis.interval[0]) * 1.1
              let newRight = realY + (series.yAxis.interval[1] - realY) * 1.1
              if (newLeft < series.yAxis.oldInterval[0]) {
                newLeft = series.yAxis.oldInterval[0]
              }
              if (newRight > series.yAxis.oldInterval[1]) {
                newRight = series.yAxis.oldInterval[1]
              }
              series.yAxis.interval[0] = newLeft
              series.yAxis.interval[1] = newRight
              // if (true) {
              //   // 根据范围内的y轴数值动态修改y轴的interval
              //   autoResize(series)
              // }
              _clearCaculatedData()
              _refresh()
              // 调用onchange
              if (series.yAxis.onYIntervalChange) {
                series.yAxis.onYIntervalChange([newLeft, newRight])
              }
            }
          }
        })
      }
    }
    _textcontainer.onmousedown = (event) => {
      const x = event.offsetX
      const y = event.offsetY
      _isMouseDown = true
      _mouseDownStart = event
      _lastMousePosition = event
      _mouseMovePre = {
        x: event.offsetX,
        y: event.offsetY
      }
    }
    _textcontainer.onmouseup = (event) => {
      _isMouseDown = false
      if (_isClickMarkLine) {
        // //console.log('之前拖动的是markline')
        // 之前拖动的是markline
        _isClickMarkLine = false
        _clickedMarkLine = null
        _clickedMarkLineSeries = null
        const x = event.offsetX
        const y = event.offsetY
        const markFindResult = _findNearestMarkLine(x, y)
        if (markFindResult) {
          if (markFindResult.markLine.type === 'x') {
            _textcontainer.style.cursor = 'ew-resize'
          }
          if (markFindResult.markLine.type === 'y') {
            _textcontainer.style.cursor = 'ns-resize'
          }
          _isClickMarkLine = true
          _clickedMarkLine = markFindResult.markLine
          _clickedMarkLineSeries = markFindResult.series

          if (markFindResult.markLine.onMouseUpListener) {
            markFindResult.markLine.onMouseUpListener(
              markFindResult.markLine.value
            )
          }
        } else {
          _textcontainer.style.cursor = ''
        }
      } else if (_isClickMeasureZone) {
        // 拖动的是x测量区域
        _isClickMeasureZone = false
        _clickedMeasureZone = null
        _clickedMeasureZoneSeries = null
      } else if (_isClickToDragMeasureZone) {
        _isClickToDragMeasureZone = false
        _clickedToDragMeasureZone = null
      } else if (_isClickXaxisPadding) {
        _isClickXaxisPadding = false
        // 调用onchange
        // if (_clickedXaxisSeries.xAxis.onXIntervalChange) {
        //   _clickedXaxisSeries.xAxis.onXIntervalChange([_clickedXaxisSeries.xAxis.interval[0], _clickedXaxisSeries.xAxis.interval[1]])
        // }
      } else {
        // 拖动距离过小 认为是click
        if (
          Math.abs(_mouseDownStart.offsetX - event.offsetX) < 10 &&
          Math.abs(_mouseDownStart.offsetY - event.offsetY) < 10
        ) {
          const startPoint = {
            x: _mouseDownStart.offsetX,
            y: _mouseDownStart.offsetY
          }
          const endPoint = {
            x: event.offsetX,
            y: event.offsetY
          }

          // 绘制鼠标点击标记
          if (_config.type === 'line') {
            _Series.forEach((series) => {
              // 不能越过边界
              if (startPoint.x < series.yAxis.padding) {
                startPoint.x = series.yAxis.padding
              }
              if (
                startPoint.x >
                _container.clientWidth - series.yAxis.defaltPadding
              ) {
                startPoint.x =
                  _container.clientWidth - series.yAxis.defaltPadding
              }
              if (startPoint.y < series.xAxis.defaltPadding) {
                startPoint.y = series.xAxis.defaltPadding
              }
              if (
                startPoint.y >
                _container.clientHeight - series.xAxis.padding
              ) {
                startPoint.y = _container.clientHeight - series.xAxis.padding
              }

              if (endPoint.x < series.yAxis.padding) {
                endPoint.x = series.yAxis.padding
              }
              if (
                endPoint.x >
                _container.clientWidth - series.yAxis.defaltPadding
              ) {
                endPoint.x =
                  _container.clientWidth - series.yAxis.defaltPadding
              }
              if (endPoint.y < series.xAxis.defaltPadding) {
                endPoint.y = series.xAxis.defaltPadding
              }
              if (endPoint.y > _container.clientHeight - series.xAxis.padding) {
                endPoint.y = _container.clientHeight - series.xAxis.padding
              }
              const startX = startPoint.x
              const startY = _container.clientHeight - startPoint.y

              const endX = endPoint.x
              const endY = _container.clientHeight - endPoint.y

              // if (_Series.length > 1) {
              // 在有多个series的情况下
              // 判断开始点是否在series内
              // 起点不在本series内的不算
              if (
                startPoint.x < series.yAxis.padding ||
                startPoint.x >
                  _container.clientWidth - series.yAxis.defaltPadding ||
                _container.clientHeight - startPoint.y < series.xAxis.padding ||
                _container.clientHeight - startPoint.y >
                  _container.clientHeight - series.xAxis.defaltPadding
              ) {
                return
              }
              // }
              const mouseClickMarkPoints = [
                series.yAxis.padding,
                endY,
                _container.clientWidth - series.yAxis.defaltPadding,
                endY,
                endX,
                series.xAxis.padding,
                endX,
                _container.clientHeight - series.xAxis.defaltPadding
              ]
              series.mouseClickMarkPoints = mouseClickMarkPoints
            })
          } else if (_config.type === 'pubu') {
          }
          _doOnclick(event)
          // 清空拉出来的矩形
          _Series.forEach((series) => {
            series.mouseStrapPoints = []
          })
          _refresh()
        } else {
          // 判断是朝左拉动还是朝右拉动
          // 拉动结束
          const startPoint = {
            x: _mouseDownStart.offsetX,
            y: _mouseDownStart.offsetY
          }
          const endPoint = {
            x: event.offsetX,
            y: event.offsetY
          }

          // 清空拉出来的矩形
          _Series.forEach((series) => {
            series.mouseStrapPoints = []
          })
          _Series.forEach((series) => {
            if (series.dragType === 'zoom') {
              if (!series.allowZoom) {
                // 禁止了缩放
                return
              }
              // 处理拉动之后的操作
              if (startPoint.x < endPoint.x) {
                // 向右拉动
                let startX = startPoint.x
                const startY = startPoint.y

                let endX = endPoint.x
                const endY = endPoint.y
                // if (_Series.length > 1) {
                // 在有多个series的情况下
                // 判断开始点是否在series内
                // 起点不在本series内的不算
                if (
                  startPoint.x < series.yAxis.padding ||
                  startPoint.x >
                    _container.clientWidth - series.yAxis.defaltPadding ||
                  _container.clientHeight - startPoint.y <
                    series.xAxis.padding ||
                  _container.clientHeight - startPoint.y >
                    _container.clientHeight - series.xAxis.defaltPadding
                ) {
                  return
                }
                // }
                // 如果当前已经到了最小间隔,则不继续处理
                if (series.xAxis.minXInterval) {
                  if (
                    series.xAxis.interval[1] - series.xAxis.interval[0] <=
                    series.xAxis.minXInterval
                  ) {
                    _clearCaculatedData()
                    _refresh()
                    return
                  }
                }
                if (startX < series.yAxis.padding) {
                  startX = series.yAxis.padding
                }
                if (
                  startX >
                  _container.clientWidth - series.yAxis.defaltPadding
                ) {
                  startX = _container.clientWidth - series.yAxis.defaltPadding
                }
                if (endX < series.yAxis.padding) {
                  endX = series.yAxis.padding
                }
                if (
                  endX >
                  _container.clientWidth - series.yAxis.defaltPadding
                ) {
                  endX = _container.clientWidth - series.yAxis.defaltPadding
                }

                // 计算开始点和结束点的对应x值
                let realStartX = _getRealXValueByXPixes(startX, series)
                let realEndX = _getRealXValueByXPixes(endX, series)

                if (series.xAxis.minXInterval) {
                  // 判断改变过后的x最大值和最小值的间隔是否小于最小x间隔
                  if (realEndX - realStartX < series.xAxis.minXInterval) {
                    realEndX = realStartX + series.xAxis.minXInterval
                    if (realEndX > series.xAxis.oldInterval[1]) {
                      realEndX = series.xAxis.oldInterval[1]
                      realStartX = realEndX - series.xAxis.minXInterval
                    }
                  }
                }
                // 设置 x轴左右间隔 刷新
                series.xAxis.interval[0] = realStartX
                series.xAxis.interval[1] = realEndX
                _clearCaculatedData()
                _refresh()
                // if (series.xAxis.onXIntervalChange) {
                _doOnXIntervalChange(series, [realStartX, realEndX])
                // }
              } else {
                // 向左拉动
                let startX = startPoint.x
                const startY = startPoint.y

                let endX = endPoint.x
                const endY = endPoint.y

                // if (_Series.length > 1) {
                // 在有多个series的情况下
                // 判断开始点是否在series内
                // 起点不在本series内的不算
                if (
                  startPoint.x < series.yAxis.padding ||
                  startPoint.x >
                    _container.clientWidth - series.yAxis.defaltPadding ||
                  _container.clientHeight - startPoint.y <
                    series.xAxis.padding ||
                  _container.clientHeight - startPoint.y >
                    _container.clientHeight - series.xAxis.defaltPadding
                ) {
                  return
                }
                // }
                if (startX < series.yAxis.padding) {
                  startX = series.yAxis.padding
                }
                if (
                  startX >
                  _container.clientWidth - series.yAxis.defaltPadding
                ) {
                  startX = _container.clientWidth - series.yAxis.defaltPadding
                }
                if (endX < series.yAxis.padding) {
                  endX = series.yAxis.padding
                }
                if (
                  endX >
                  _container.clientWidth - series.yAxis.defaltPadding
                ) {
                  endX = _container.clientWidth - series.yAxis.defaltPadding
                }

                // 恢复 x轴左右间隔 刷新
                series.xAxis.interval[0] = series.xAxis.oldInterval[0]
                series.xAxis.interval[1] = series.xAxis.oldInterval[1]

                if (_config.type === 'line') {
                  // console.log('左上画矩形:', series)
                  series.yAxis.interval[0] = series.yAxis.oldInterval[0]
                  series.yAxis.interval[1] = series.yAxis.oldInterval[1]
                }

                _clearCaculatedData()
                _refresh()
                // if (series.xAxis.onXIntervalChange) {
                _doOnXIntervalChange(series, [
                  _Series[0].xAxis.oldInterval[0],
                  _Series[0].xAxis.oldInterval[1]
                ])
                // }
              }
            }
            if (series.dragType === 'measure') {
              _Series.forEach((series) => {
                let startX = startPoint.x
                let startY = startPoint.y

                let endX = endPoint.x
                let endY = endPoint.y

                // if (_Series.length > 1) {
                // 在有多个series的情况下
                // 判断开始点是否在series内
                // 起点不在本series内的不算
                if (
                  startPoint.x < series.yAxis.padding ||
                  startPoint.x >
                    _container.clientWidth - series.yAxis.defaltPadding ||
                  _container.clientHeight - startPoint.y <
                    series.xAxis.padding ||
                  _container.clientHeight - startPoint.y >
                    _container.clientHeight - series.xAxis.defaltPadding
                ) {
                  return
                }
                // }
                if (startX < series.yAxis.padding) {
                  startX = series.yAxis.padding
                }
                if (
                  startX >
                  _container.clientWidth - series.yAxis.defaltPadding
                ) {
                  startX = _container.clientWidth - series.yAxis.defaltPadding
                }
                if (endX < series.yAxis.padding) {
                  endX = series.yAxis.padding
                }
                if (
                  endX >
                  _container.clientWidth - series.yAxis.defaltPadding
                ) {
                  endX = _container.clientWidth - series.yAxis.defaltPadding
                }

                if (startY < series.xAxis.padding) {
                  startY = series.xAxis.padding
                }
                if (
                  startY >
                  _container.clientHeight - series.xAxis.defaltPadding
                ) {
                  startY = _container.clientHeight - series.xAxis.defaltPadding
                }
                if (endY < series.xAxis.padding) {
                  endY = series.xAxis.padding
                }
                if (
                  endY >
                  _container.clientHeight - series.xAxis.defaltPadding
                ) {
                  endY = _container.clientHeight - series.xAxis.defaltPadding
                }
                _refresh()
                if (_config.type === 'line') {
                  const realStartX = _getRealXValueByXPixes(startX, series)
                  const realStartY = _getRealYValueByYPixes(
                    _container.clientHeight - startY,
                    series
                  )

                  const realEndX = _getRealXValueByXPixes(endX, series)
                  const realEndY = _getRealYValueByYPixes(
                    _container.clientHeight - endY,
                    series
                  )

                  if (series.onMeasureListener) {
                    series.onMeasureListener(
                      realStartX,
                      realStartY,
                      realEndX,
                      realEndY
                    )
                  }
                } else if (_config.type === 'pubu') {
                  if (series.yAxis.timeStamps.length === 0) {
                    return
                  }
                  const realStartX = _getRealXValueByXPixes(startX, series)
                  const realStartY = _getRealYValueByYPixes(
                    _container.clientHeight - startY,
                    series
                  )

                  const realEndX = _getRealXValueByXPixes(endX, series)
                  const realEndY = _getRealYValueByYPixes(
                    _container.clientHeight - endY,
                    series
                  )
                  // 需要将realX转化成真实时间戳
                  const startidx = series.yAxis.interval[1] - realStartY
                  const realYrealStartYValue =
                    series.yAxis.timeStamps[
                      series.yAxis.timeStamps.length - 1 - Math.round(startidx)
                    ]

                  const endidx = series.yAxis.interval[1] - realEndY
                  const realEndYValue =
                    series.yAxis.timeStamps[
                      series.yAxis.timeStamps.length - 1 - Math.round(endidx)
                    ]

                  if (series.onMeasureListener) {
                    series.onMeasureListener(
                      realStartX,
                      realYrealStartYValue,
                      realEndX,
                      realEndYValue
                    )
                  }
                  // 判断是否打开了timemeasure 绘制矩形
                  if (series.timeMeasureOpen) {
                    // 计算时间
                    series.timeMeasure = {
                      type: 'time',
                      startX: startX,
                      endX: endX,
                      startY: _container.clientHeight - startY,
                      endY: _container.clientHeight - endY,
                      words: [
                        {
                          x:
                            startX -
                            _textCtx.measureText(
                              getHHmmssSSS(realYrealStartYValue)
                            ).width,
                          y: startY + 10,
                          str: getHHmmssSSS(realYrealStartYValue)
                        },
                        {
                          x:
                            startX -
                            _textCtx.measureText(getHHmmssSSS(realEndYValue))
                              .width,
                          y: endY,
                          str: getHHmmssSSS(realEndYValue)
                        }
                      ]
                    }
                  }
                  // let realX = _getRealXValueByXPixes(x, series)
                  // // y坐标从下往上递增
                  // let realY = _getRealYValueByYPixes(_container.clientHeight - y, series)
                  // // 查看鼠标是否移动到y轴mark上了
                  // //console.log(series)
                  // // 需要将realX转化成真实时间戳
                  // let idx = series.yAxis.interval[1] - realY
                  // let realYValue = series.yAxis.timeStamps[(series.yAxis.timeStamps.length - 1) - Math.round(idx)]

                  // if (series.onMouseMoveListener) {
                  //   series.onMouseMoveListener(realX, realYValue, event)
                  // }
                }
              })
            }
          })
        }
      }
      _mouseMovePre = null
    }
    _textcontainer.onmousemove = (event) => {
      if (_isMouseDown) {
        // 鼠标点击拖动 绘制方框
        const startPoint = {
          x: _mouseDownStart.offsetX,
          y: _mouseDownStart.offsetY
        }
        const endPoint = {
          x: event.offsetX,
          y: event.offsetY
        }
        if (_isClickMarkLine) {
          // 拖动的是markline
          // 不能越过边界
          if (startPoint.x < _clickedMarkLineSeries.yAxis.padding) {
            startPoint.x = _clickedMarkLineSeries.yAxis.padding
          }
          if (
            startPoint.x >
            _container.clientWidth - _clickedMarkLineSeries.yAxis.defaltPadding
          ) {
            startPoint.x =
              _container.clientWidth -
              _clickedMarkLineSeries.yAxis.defaltPadding
          }
          if (startPoint.y < _clickedMarkLineSeries.xAxis.defaltPadding) {
            startPoint.y = _clickedMarkLineSeries.xAxis.defaltPadding
          }
          if (
            startPoint.y >
            _container.clientHeight - _clickedMarkLineSeries.xAxis.padding
          ) {
            startPoint.y =
              _container.clientHeight - _clickedMarkLineSeries.xAxis.padding
          }

          if (endPoint.x < _clickedMarkLineSeries.yAxis.padding) {
            endPoint.x = _clickedMarkLineSeries.yAxis.padding
          }
          if (
            endPoint.x >
            _container.clientWidth - _clickedMarkLineSeries.yAxis.defaltPadding
          ) {
            endPoint.x =
              _container.clientWidth -
              _clickedMarkLineSeries.yAxis.defaltPadding
          }
          if (endPoint.y < _clickedMarkLineSeries.xAxis.defaltPadding) {
            endPoint.y = _clickedMarkLineSeries.xAxis.defaltPadding
          }
          if (
            endPoint.y >
            _container.clientHeight - _clickedMarkLineSeries.xAxis.padding
          ) {
            endPoint.y =
              _container.clientHeight - _clickedMarkLineSeries.xAxis.padding
          }

          _clickedMarkLine.pixes = endPoint
          if (_clickedMarkLine.type === 'x') {
            const pixes = endPoint.x
            const realXValue = _getRealXValueByXPixes(
              pixes,
              _clickedMarkLineSeries
            )
            _clickedMarkLine.pixes = pixes
            _clickedMarkLine.value = realXValue
            _clickedMarkLine.points = []
            if (_clickedMarkLine.onValueChangeListener) {
              _clickedMarkLine.onValueChangeListener(realXValue)
            }
          }
          if (_clickedMarkLine.type === 'y') {
            const pixes = _container.clientHeight - endPoint.y
            const realYValue = _getRealYValueByYPixes(
              pixes,
              _clickedMarkLineSeries
            )
            _clickedMarkLine.pixes = pixes
            _clickedMarkLine.value = realYValue
            _clickedMarkLine.points = []
            if (_clickedMarkLine.onValueChangeListener) {
              _clickedMarkLine.onValueChangeListener(realYValue)
            }
          }
        } else if (_isClickMeasureZone) {
          // console.log("!!!!!!!!!")
          // 拖动了测量区域
          // 不能越过边界
          if (startPoint.x < _clickedMeasureZone.series.yAxis.padding) {
            startPoint.x = _clickedMeasureZone.series.yAxis.padding
          }
          if (
            startPoint.x >
            _container.clientWidth -
              _clickedMeasureZone.series.yAxis.defaltPadding
          ) {
            startPoint.x =
              _container.clientWidth -
              _clickedMeasureZone.series.yAxis.defaltPadding
          }
          if (startPoint.y < _clickedMeasureZone.series.xAxis.defaltPadding) {
            startPoint.y = _clickedMeasureZone.series.xAxis.defaltPadding
          }
          if (
            startPoint.y >
            _container.clientHeight - _clickedMeasureZone.series.xAxis.padding
          ) {
            startPoint.y =
              _container.clientHeight -
              _clickedMeasureZone.series.xAxis.padding
          }

          if (endPoint.x < _clickedMeasureZone.series.yAxis.padding) {
            endPoint.x = _clickedMeasureZone.series.yAxis.padding
          }
          if (
            endPoint.x >
            _container.clientWidth -
              _clickedMeasureZone.series.yAxis.defaltPadding
          ) {
            endPoint.x =
              _container.clientWidth -
              _clickedMeasureZone.series.yAxis.defaltPadding
          }
          if (endPoint.y < _clickedMeasureZone.series.xAxis.defaltPadding) {
            endPoint.y = _clickedMeasureZone.series.xAxis.defaltPadding
          }
          if (
            endPoint.y >
            _container.clientHeight - _clickedMeasureZone.series.xAxis.padding
          ) {
            endPoint.y =
              _container.clientHeight -
              _clickedMeasureZone.series.xAxis.padding
          }

          if (_clickedMeasureZone.direction === 'left') {
            const xPixes = endPoint.x
            if (_clickedMeasureZone.measureZone.type === 'freq') {
              _clickedMeasureZone.measureZone.startX = xPixes
              _clickedMeasureZone.series.freqMeasure.points = []
              const realstartXValue = _getRealXValueByXPixes(
                _clickedMeasureZone.measureZone.startX,
                _clickedMeasureZone.series
              )
              const realendXValue = _getRealXValueByXPixes(
                _clickedMeasureZone.measureZone.endX,
                _clickedMeasureZone.series
              )
              _clickedMeasureZone.measureZone.words = [
                {
                  x: _clickedMeasureZone.measureZone.endX,
                  y: _container.clientHeight / 2,
                  str: _clickedMeasureZone.series.xAxis.xAxisMarkFormatter
                    ? _clickedMeasureZone.series.xAxis.xAxisMarkFormatter(
                      realendXValue.toFixed(2)
                    )
                    : realendXValue.toFixed(2).toString()
                },
                {
                  x: _clickedMeasureZone.measureZone.startX,
                  y: _container.clientHeight / 2,
                  str: _clickedMeasureZone.series.xAxis.xAxisMarkFormatter
                    ? _clickedMeasureZone.series.xAxis.xAxisMarkFormatter(
                      realstartXValue.toFixed(2)
                    )
                    : realstartXValue.toFixed(2).toString()
                }
              ]
            }
          } else if (_clickedMeasureZone.direction === 'right') {
            const xPixes = endPoint.x
            if (_clickedMeasureZone.measureZone.type === 'freq') {
              _clickedMeasureZone.measureZone.endX = xPixes
              _clickedMeasureZone.series.freqMeasure.points = []
              const realstartXValue = _getRealXValueByXPixes(
                _clickedMeasureZone.measureZone.startX,
                _clickedMeasureZone.series
              )
              const realendXValue = _getRealXValueByXPixes(
                _clickedMeasureZone.measureZone.endX,
                _clickedMeasureZone.series
              )
              _clickedMeasureZone.measureZone.words = [
                {
                  x: _clickedMeasureZone.measureZone.endX,
                  y: _container.clientHeight / 2,
                  str: _clickedMeasureZone.series.xAxis.xAxisMarkFormatter
                    ? _clickedMeasureZone.series.xAxis.xAxisMarkFormatter(
                      realendXValue.toFixed(2)
                    )
                    : realendXValue.toFixed(2).toString()
                },
                {
                  x: _clickedMeasureZone.measureZone.startX,
                  y: _container.clientHeight / 2,
                  str: _clickedMeasureZone.series.xAxis.xAxisMarkFormatter
                    ? _clickedMeasureZone.series.xAxis.xAxisMarkFormatter(
                      realstartXValue.toFixed(2)
                    )
                    : realstartXValue.toFixed(2).toString()
                }
              ]
            }
          } else if (_clickedMeasureZone.direction === 'bottom') {
            const yPixes = _container.clientHeight - endPoint.y
            if (_clickedMeasureZone.measureZone.type === 'SNR') {
              _clickedMeasureZone.measureZone.startY = yPixes
              _clickedMeasureZone.series.SNRMeasure.points = []
              const realstartYValue = _getRealYValueByYPixes(
                _clickedMeasureZone.measureZone.startY,
                _clickedMeasureZone.series
              )
              const realendYValue = _getRealYValueByYPixes(
                _clickedMeasureZone.measureZone.endY,
                _clickedMeasureZone.series
              )
              _clickedMeasureZone.measureZone.words = [
                {
                  x: _clickedMeasureZone.measureZone.endX,
                  y:
                    _container.clientHeight -
                    _clickedMeasureZone.measureZone.endY,
                  str: _clickedMeasureZone.series.yAxis.yAxisMarkFormatter
                    ? _clickedMeasureZone.series.yAxis.yAxisMarkFormatter(
                      realendYValue.toFixed(2)
                    )
                    : realendYValue.toFixed(2).toString()
                },
                {
                  x: _clickedMeasureZone.measureZone.endX,
                  y:
                    _container.clientHeight -
                    _clickedMeasureZone.measureZone.startY,
                  str: _clickedMeasureZone.series.yAxis.yAxisMarkFormatter
                    ? _clickedMeasureZone.series.yAxis.yAxisMarkFormatter(
                      realstartYValue.toFixed(2)
                    )
                    : realstartYValue.toFixed(2).toString()
                }
              ]
            } else if (_clickedMeasureZone.measureZone.type === 'time') {
              _clickedMeasureZone.measureZone.startY = yPixes
              const realstartYValue = _getRealYValueByYPixes(
                _clickedMeasureZone.measureZone.startY,
                _clickedMeasureZone.series
              )
              // 需要将realY转化成真实时间戳
              const startidx =
                _clickedMeasureZone.series.yAxis.interval[1] - realstartYValue
              const realrealstartYTimeStamp =
                _clickedMeasureZone.series.yAxis.timeStamps[
                  _clickedMeasureZone.series.yAxis.timeStamps.length -
                    1 -
                    Math.round(startidx)
                ]

              // 计算时间
              _clickedMeasureZone.measureZone.points = []
              _clickedMeasureZone.measureZone.startY = yPixes
              const oldwords = _clickedMeasureZone.measureZone.words
              _clickedMeasureZone.measureZone.words = [
                {
                  x:
                    _clickedMeasureZone.measureZone.startX -
                    _textCtx.measureText(getHHmmssSSS(realrealstartYTimeStamp))
                      .width,
                  y: _container.clientHeight - yPixes,
                  str: getHHmmssSSS(realrealstartYTimeStamp)
                },
                oldwords[1]
              ]
            }
          } else if (_clickedMeasureZone.direction === 'top') {
            // console.log("top")
            const yPixes = _container.clientHeight - endPoint.y
            if (_clickedMeasureZone.measureZone.type === 'SNR') {
              _clickedMeasureZone.measureZone.endY = yPixes
              _clickedMeasureZone.series.SNRMeasure.points = []
              const realstartYValue = _getRealYValueByYPixes(
                _clickedMeasureZone.measureZone.startY,
                _clickedMeasureZone.series
              )
              const realendYValue = _getRealYValueByYPixes(
                _clickedMeasureZone.measureZone.endY,
                _clickedMeasureZone.series
              )
              _clickedMeasureZone.measureZone.words = [
                {
                  x: _clickedMeasureZone.measureZone.endX,
                  y:
                    _container.clientHeight -
                    _clickedMeasureZone.measureZone.endY,
                  str: _clickedMeasureZone.series.yAxis.yAxisMarkFormatter
                    ? _clickedMeasureZone.series.yAxis.yAxisMarkFormatter(
                      realendYValue.toFixed(2)
                    )
                    : realendYValue.toFixed(2).toString()
                },
                {
                  x: _clickedMeasureZone.measureZone.endX,
                  y:
                    _container.clientHeight -
                    _clickedMeasureZone.measureZone.startY,
                  str: _clickedMeasureZone.series.yAxis.yAxisMarkFormatter
                    ? _clickedMeasureZone.series.yAxis.yAxisMarkFormatter(
                      realstartYValue.toFixed(2)
                    )
                    : realstartYValue.toFixed(2).toString()
                }
              ]
            } else if (_clickedMeasureZone.measureZone.type === 'time') {
              _clickedMeasureZone.measureZone.endY = yPixes
              const realendYValue = _getRealYValueByYPixes(
                _clickedMeasureZone.measureZone.endY,
                _clickedMeasureZone.series
              )
              // 需要将realY转化成真实时间戳
              const startidx =
                _clickedMeasureZone.series.yAxis.interval[1] - realendYValue
              const realrealendYTimeStamp =
                _clickedMeasureZone.series.yAxis.timeStamps[
                  _clickedMeasureZone.series.yAxis.timeStamps.length -
                    1 -
                    Math.round(startidx)
                ]

              // 计算时间
              _clickedMeasureZone.measureZone.points = []
              _clickedMeasureZone.measureZone.endY = yPixes
              const oldwords = _clickedMeasureZone.measureZone.words
              _clickedMeasureZone.measureZone.words = [
                oldwords[0],
                {
                  x:
                    _clickedMeasureZone.measureZone.startX -
                    _textCtx.measureText(getHHmmssSSS(realrealendYTimeStamp))
                      .width,
                  y: _container.clientHeight - yPixes,
                  str: getHHmmssSSS(realrealendYTimeStamp)
                }
              ]
            }
          } else if (_clickedMeasureZone.direction === 'all') {
            const xPixes = endPoint.x
            if (_clickedMeasureZone.measureZone.type === 'kdCollection') {
              const xMoveDistance = event.offsetX - _lastMousePosition.offsetX
              // //console.log("xMoveDistance " + xMoveDistance)

              // //console.log("kdCollectionPosition " +  _clickedMeasureZone.measureZone.kdCollectionPosition)

              let newKdCollectionPosition =
                _clickedMeasureZone.measureZone.kdCollectionPosition +
                xMoveDistance
              // //console.log("newKdCollectionPosition " + newKdCollectionPosition)

              // //console.log("kdCollectionPositionValue " + _clickedMeasureZone.measureZone.kdCollectionPositionValue)
              let newkdCollectionPositionValue = _getRealXValueByXPixes(
                newKdCollectionPosition,
                _clickedMeasureZone.series
              )

              // //console.log("newkdCollectionPositionValue " + newkdCollectionPositionValue)
              // debugger
              // 判断是否超出边界
              let startX =
                newKdCollectionPosition -
                _clickedMeasureZone.measureZone.collectonZoneWidth / 2
              let endX =
                newKdCollectionPosition +
                _clickedMeasureZone.measureZone.collectonZoneWidth / 2

              if (startX < _clickedMeasureZone.series.yAxis.padding) {
                startX = _clickedMeasureZone.series.yAxis.padding
                endX =
                  startX + _clickedMeasureZone.measureZone.collectonZoneWidth
                newKdCollectionPosition =
                  startX +
                  _clickedMeasureZone.measureZone.collectonZoneWidth / 2
                newkdCollectionPositionValue = _getRealXValueByXPixes(
                  newKdCollectionPosition,
                  _clickedMeasureZone.series
                )
              }
              if (
                endX >
                _container.clientWidth -
                  _clickedMeasureZone.series.yAxis.defaltPadding
              ) {
                endX =
                  _container.clientWidth -
                  _clickedMeasureZone.series.yAxis.defaltPadding
                startX =
                  endX - _clickedMeasureZone.measureZone.collectonZoneWidth

                newKdCollectionPosition =
                  startX +
                  _clickedMeasureZone.measureZone.collectonZoneWidth / 2
                newkdCollectionPositionValue = _getRealXValueByXPixes(
                  newKdCollectionPosition,
                  _clickedMeasureZone.series
                )
              }
              _clickedMeasureZone.measureZone.kdCollectionPosition =
                newKdCollectionPosition
              _clickedMeasureZone.measureZone.kdCollectionPositionValue =
                newkdCollectionPositionValue

              _clickedMeasureZone.measureZone.startX =
                newKdCollectionPosition -
                _clickedMeasureZone.measureZone.collectonZoneWidth / 2
              _clickedMeasureZone.measureZone.endX =
                newKdCollectionPosition +
                _clickedMeasureZone.measureZone.collectonZoneWidth / 2
              _clickedMeasureZone.measureZone.points = []

              if (_clickedMeasureZone.series.kdCollectionListener) {
                _clickedMeasureZone.series.kdCollectionListener(
                  newkdCollectionPositionValue
                )
              }
              // //console.log("newkdCollectionPositionValue:" + newkdCollectionPositionValue / 1000000)
            }
            _lastMousePosition = event
          }
        } else if (_isClickToDragMeasureZone) {
          // 拖动了测量区域内部
          // 计算出在x轴和y轴拖动的距离

          let yDragLength = 0
          if (_mouseMovePre) {
            yDragLength =
              _container.clientHeight -
              endPoint.y -
              (_container.clientHeight - _mouseMovePre.y)
          } else {
            yDragLength =
              _container.clientHeight -
              endPoint.y -
              (_container.clientHeight - startPoint.y)
          }
          let xDragLength = 0
          if (_mouseMovePre) {
            xDragLength = endPoint.x - _mouseMovePre.x
          } else {
            xDragLength = endPoint.x - startPoint.x
          }
          const xPixes = endPoint.x
          if (_clickedToDragMeasureZone.measureZone.type === 'freq') {
            if (
              _clickedToDragMeasureZone.measureZone.startX + xDragLength <
              _clickedToDragMeasureZone.series.yAxis.padding
            ) {
              xDragLength =
                _clickedToDragMeasureZone.measureZone.startX -
                _clickedToDragMeasureZone.series.yAxis.padding
            }
            if (
              _clickedToDragMeasureZone.measureZone.endX + xDragLength >
              _container.clientWidth -
                _clickedToDragMeasureZone.series.yAxis.defaltPadding
            ) {
              xDragLength =
                _container.clientWidth -
                _clickedToDragMeasureZone.series.yAxis.defaltPadding -
                _clickedToDragMeasureZone.measureZone.endX
            }
            _clickedToDragMeasureZone.measureZone.startX =
              _clickedToDragMeasureZone.measureZone.startX + xDragLength
            _clickedToDragMeasureZone.measureZone.endX =
              _clickedToDragMeasureZone.measureZone.endX + xDragLength
            _clickedToDragMeasureZone.series.freqMeasure.points = []
            const realstartXValue = _getRealXValueByXPixes(
              _clickedToDragMeasureZone.measureZone.startX,
              _clickedToDragMeasureZone.series
            )
            const realendXValue = _getRealXValueByXPixes(
              _clickedToDragMeasureZone.measureZone.endX,
              _clickedToDragMeasureZone.series
            )

            _clickedToDragMeasureZone.measureZone.words = [
              {
                x: _clickedToDragMeasureZone.measureZone.endX,
                y: _container.clientHeight / 2,
                str: _clickedToDragMeasureZone.series.xAxis.xAxisMarkFormatter
                  ? _clickedToDragMeasureZone.series.xAxis.xAxisMarkFormatter(
                    realendXValue.toFixed(2)
                  )
                  : realendXValue.toFixed(2).toString()
              },
              {
                x: _clickedToDragMeasureZone.measureZone.startX,
                y: _container.clientHeight / 2,
                str: _clickedToDragMeasureZone.series.xAxis.xAxisMarkFormatter
                  ? _clickedToDragMeasureZone.series.xAxis.xAxisMarkFormatter(
                    realstartXValue.toFixed(2)
                  )
                  : realstartXValue.toFixed(2).toString()
              }
            ]
          }
          if (_clickedToDragMeasureZone.measureZone.type === 'SNR') {
            if (
              _clickedToDragMeasureZone.measureZone.startX + xDragLength <
              _clickedToDragMeasureZone.series.yAxis.padding
            ) {
              xDragLength =
                _clickedToDragMeasureZone.measureZone.startX -
                _clickedToDragMeasureZone.series.yAxis.padding
            }
            if (
              _clickedToDragMeasureZone.measureZone.endX + xDragLength >
              _container.clientWidth -
                _clickedToDragMeasureZone.series.yAxis.defaltPadding
            ) {
              xDragLength =
                _container.clientWidth -
                _clickedToDragMeasureZone.series.yAxis.defaltPadding -
                _clickedToDragMeasureZone.measureZone.endX
            }

            if (
              _clickedToDragMeasureZone.measureZone.startY + yDragLength <
              _clickedToDragMeasureZone.series.xAxis.padding
            ) {
              yDragLength =
                _clickedToDragMeasureZone.measureZone.startY -
                _clickedToDragMeasureZone.series.xAxis.padding
            }
            if (
              _clickedToDragMeasureZone.measureZone.endY + yDragLength >
              _container.clientHeight -
                _clickedToDragMeasureZone.series.xAxis.defaltPadding
            ) {
              yDragLength =
                _container.clientHeight -
                _clickedToDragMeasureZone.series.xAxis.defaltPadding -
                _clickedToDragMeasureZone.measureZone.endY
            }
            _clickedToDragMeasureZone.measureZone.startX =
              _clickedToDragMeasureZone.measureZone.startX + xDragLength
            _clickedToDragMeasureZone.measureZone.endX =
              _clickedToDragMeasureZone.measureZone.endX + xDragLength
            _clickedToDragMeasureZone.measureZone.startY =
              _clickedToDragMeasureZone.measureZone.startY + yDragLength
            _clickedToDragMeasureZone.measureZone.endY =
              _clickedToDragMeasureZone.measureZone.endY + yDragLength

            _clickedToDragMeasureZone.series.SNRMeasure.points = []
            const realstartYValue = _getRealYValueByYPixes(
              _clickedToDragMeasureZone.measureZone.startY,
              _clickedToDragMeasureZone.series
            )
            const realendYValue = _getRealYValueByYPixes(
              _clickedToDragMeasureZone.measureZone.endY,
              _clickedToDragMeasureZone.series
            )

            _clickedToDragMeasureZone.measureZone.words = [
              {
                x: _clickedToDragMeasureZone.measureZone.endX,
                y:
                  _container.clientHeight -
                  _clickedToDragMeasureZone.measureZone.endY,
                str: _clickedToDragMeasureZone.series.yAxis.yAxisMarkFormatter
                  ? _clickedToDragMeasureZone.series.yAxis.yAxisMarkFormatter(
                    realendYValue.toFixed(2)
                  )
                  : realendYValue.toFixed(2).toString()
              },
              {
                x: _clickedToDragMeasureZone.measureZone.endX,
                y:
                  _container.clientHeight -
                  _clickedToDragMeasureZone.measureZone.startY,
                str: _clickedToDragMeasureZone.series.yAxis.yAxisMarkFormatter
                  ? _clickedToDragMeasureZone.series.yAxis.yAxisMarkFormatter(
                    realstartYValue.toFixed(2)
                  )
                  : realstartYValue.toFixed(2).toString()
              }
            ]
          }

          if (_clickedToDragMeasureZone.measureZone.type === 'time') {
            if (
              _clickedToDragMeasureZone.measureZone.startX + xDragLength <
              _clickedToDragMeasureZone.series.yAxis.padding
            ) {
              xDragLength =
                _clickedToDragMeasureZone.measureZone.startX -
                _clickedToDragMeasureZone.series.yAxis.padding
            }
            if (
              _clickedToDragMeasureZone.measureZone.endX + xDragLength >
              _container.clientWidth -
                _clickedToDragMeasureZone.series.yAxis.defaltPadding
            ) {
              xDragLength =
                _container.clientWidth -
                _clickedToDragMeasureZone.series.yAxis.defaltPadding -
                _clickedToDragMeasureZone.measureZone.endX
            }

            if (
              _clickedToDragMeasureZone.measureZone.startY + yDragLength <
              _clickedToDragMeasureZone.series.xAxis.padding
            ) {
              yDragLength =
                _clickedToDragMeasureZone.measureZone.startY -
                _clickedToDragMeasureZone.series.xAxis.padding
            }
            if (
              _clickedToDragMeasureZone.measureZone.endY + yDragLength >
              _container.clientHeight -
                _clickedToDragMeasureZone.series.xAxis.defaltPadding
            ) {
              yDragLength =
                _container.clientHeight -
                _clickedToDragMeasureZone.series.xAxis.defaltPadding -
                _clickedToDragMeasureZone.measureZone.endY
            }
            const startX =
              _clickedToDragMeasureZone.measureZone.startX + xDragLength
            const endX =
              _clickedToDragMeasureZone.measureZone.endX + xDragLength
            const startY =
              _clickedToDragMeasureZone.measureZone.startY + yDragLength
            const endY =
              _clickedToDragMeasureZone.measureZone.endY + yDragLength

            const realStartX = _getRealXValueByXPixes(
              startX,
              _clickedToDragMeasureZone.series
            )
            const realStartY = _getRealYValueByYPixes(
              startY,
              _clickedToDragMeasureZone.series
            )

            const realEndX = _getRealXValueByXPixes(
              endX,
              _clickedToDragMeasureZone.series
            )
            const realEndY = _getRealYValueByYPixes(
              endY,
              _clickedToDragMeasureZone.series
            )

            // 需要将realY转化成真实时间戳
            const startidx =
              _clickedToDragMeasureZone.series.yAxis.interval[1] - realStartY
            const realYrealStartYValue =
              _clickedToDragMeasureZone.series.yAxis.timeStamps[
                _clickedToDragMeasureZone.series.yAxis.timeStamps.length -
                  1 -
                  Math.round(startidx)
              ]

            const endidx =
              _clickedToDragMeasureZone.series.yAxis.interval[1] - realEndY
            const realEndYValue =
              _clickedToDragMeasureZone.series.yAxis.timeStamps[
                _clickedToDragMeasureZone.series.yAxis.timeStamps.length -
                  1 -
                  Math.round(endidx)
              ]
            // 计算时间
            _clickedToDragMeasureZone.measureZone.points = []
            _clickedToDragMeasureZone.measureZone.startX = startX
            _clickedToDragMeasureZone.measureZone.endX = endX
            _clickedToDragMeasureZone.measureZone.startY = startY
            _clickedToDragMeasureZone.measureZone.endY = endY

            _clickedToDragMeasureZone.measureZone.words = [
              {
                x:
                  startX -
                  _textCtx.measureText(getHHmmssSSS(realYrealStartYValue))
                    .width,
                y: _container.clientHeight - startY + 10,
                str: getHHmmssSSS(realYrealStartYValue)
              },
              {
                x:
                  startX -
                  _textCtx.measureText(getHHmmssSSS(realEndYValue)).width,
                y: _container.clientHeight - endY,
                str: getHHmmssSSS(realEndYValue)
              }
            ]
          }
          _mouseMovePre = {
            x: event.offsetX,
            y: event.offsetY
          }
        } else if (_isClickYaxisPadding) {
          // 向上拖动y轴
          // let realYvalue = _getRealYValueByYPixes()
          let dragLength = 0
          if (_mouseMovePre) {
            dragLength =
              _container.clientHeight -
              endPoint.y -
              (_container.clientHeight - _mouseMovePre.y)
          } else {
            dragLength =
              _container.clientHeight -
              endPoint.y -
              (_container.clientHeight - startPoint.y)
          }
          const percent =
            dragLength /
            (_container.clientHeight -
              _clickedYaxisSeries.xAxis.padding -
              _clickedYaxisSeries.xAxis.defaltPadding)
          const dragValue =
            (_clickedYaxisSeries.yAxis.interval[1] -
              _clickedYaxisSeries.yAxis.interval[0]) *
            percent
          // dragLength > 0 朝上 <0 朝下
          let startYValue = _clickedYaxisSeries.yAxis.interval[0] - dragValue
          let endYValue = _clickedYaxisSeries.yAxis.interval[1] - dragValue
          if (startYValue <= _clickedYaxisSeries.yAxis.oldInterval[0]) {
            // console.log('11', startYValue, _clickedYaxisSeries.yAxis.oldInterval)
            const movedValue =
              _clickedYaxisSeries.yAxis.oldInterval[0] -
              _clickedYaxisSeries.yAxis.interval[0]
            startYValue = _clickedYaxisSeries.yAxis.oldInterval[0]
            endYValue = _clickedYaxisSeries.yAxis.interval[1] - movedValue
          }
          if (endYValue >= _clickedYaxisSeries.yAxis.oldInterval[1]) {
            // console.log('22', endYValue, _clickedYaxisSeries.yAxis.oldInterval)
            const movedValue =
              _clickedYaxisSeries.yAxis.oldInterval[1] -
              _clickedYaxisSeries.yAxis.interval[1]
            startYValue = _clickedYaxisSeries.yAxis.interval[0] + movedValue
            endYValue = _clickedYaxisSeries.yAxis.oldInterval[1]
          }

          // console.log('起始区间', startYValue, endYValue)
          _clickedYaxisSeries.yAxis.interval = [startYValue, endYValue]
          _clearCaculatedData()

          // 调用onchange
          if (_clickedYaxisSeries.yAxis.onYIntervalChange) {
            _clickedYaxisSeries.yAxis.onYIntervalChange([
              startYValue,
              endYValue
            ])
          }
          _mouseMovePre = {
            x: event.offsetX,
            y: event.offsetY
          }
        } else if (_isClickXaxisPadding) {
          // 拖动x轴
          let dragLength = 0
          if (_mouseMovePre) {
            dragLength = endPoint.x - _mouseMovePre.x
          } else {
            dragLength = endPoint.x - startPoint.x
          }
          const percent =
            dragLength /
            (_container.clientWidth -
              _clickedXaxisSeries.yAxis.padding -
              _clickedXaxisSeries.yAxis.defaltPadding)
          const dragValue =
            (_clickedXaxisSeries.xAxis.interval[1] -
              _clickedXaxisSeries.xAxis.interval[0]) *
            percent
          // //console.log(dragLength)
          // //console.log(dragValue)
          // dragLength > 0 朝右 <0 朝左
          let startXValue = _clickedXaxisSeries.xAxis.interval[0] - dragValue
          let endXValue = _clickedXaxisSeries.xAxis.interval[1] - dragValue

          if (startXValue <= _clickedXaxisSeries.xAxis.oldInterval[0]) {
            const movedValue =
              _clickedXaxisSeries.xAxis.interval[0] -
              _clickedXaxisSeries.xAxis.oldInterval[0]
            startXValue = _clickedXaxisSeries.xAxis.oldInterval[0]
            endXValue = _clickedXaxisSeries.xAxis.interval[1] - movedValue
          }
          if (endXValue >= _clickedXaxisSeries.xAxis.oldInterval[1]) {
            const movedValue =
              _clickedXaxisSeries.xAxis.oldInterval[1] -
              _clickedXaxisSeries.xAxis.interval[1]
            startXValue = _clickedXaxisSeries.xAxis.interval[0] + movedValue
            endXValue = _clickedXaxisSeries.xAxis.oldInterval[1]
          }

          _clickedXaxisSeries.xAxis.interval = [startXValue, endXValue]
          _clearCaculatedData()

          _clickedXaxisSeries.throttleOnXIntervalChange()
          //
          _mouseMovePre = {
            x: event.offsetX,
            y: event.offsetY
          }
        } else {
          _Series.forEach((series) => {
            let startX = startPoint.x
            let startY = startPoint.y
            let endX = endPoint.x
            let endY = endPoint.y

            // if (_Series.length > 1) {
            // 在有多个series的情况下
            // 起点不在本series内的不算
            if (
              startPoint.x < series.yAxis.padding ||
              startPoint.x >
                _container.clientWidth - series.yAxis.defaltPadding ||
              _container.clientHeight - startPoint.y < series.xAxis.padding ||
              _container.clientHeight - startPoint.y >
                _container.clientHeight - series.xAxis.defaltPadding
            ) {
              return
            }
            // }

            // 不能越过边界
            if (startX < series.yAxis.padding) {
              startX = series.yAxis.padding
            }
            if (startX > _container.clientWidth - series.yAxis.defaltPadding) {
              startX = _container.clientWidth - series.yAxis.defaltPadding
            }
            if (startY < series.xAxis.defaltPadding) {
              startY = series.xAxis.defaltPadding
            }
            if (startY > _container.clientHeight - series.xAxis.padding) {
              startY = _container.clientHeight - series.xAxis.padding
            }

            if (endX < series.yAxis.padding) {
              endX = series.yAxis.padding
            }
            if (endX > _container.clientWidth - series.yAxis.defaltPadding) {
              endX = _container.clientWidth - series.yAxis.defaltPadding
            }
            if (endY < series.xAxis.defaltPadding) {
              endY = series.xAxis.defaltPadding
            }
            if (endY > _container.clientHeight - series.xAxis.padding) {
              endY = _container.clientHeight - series.xAxis.padding
            }
            if (series.dragType === 'zoom') {
              series.mouseStrapPoints = []
              // y轴贯通
              series.mouseStrapPoints.push(startX)
              series.mouseStrapPoints.push(series.xAxis.padding)
              series.mouseStrapPoints.push(endX)
              series.mouseStrapPoints.push(series.xAxis.padding)
              series.mouseStrapPoints.push(endX)
              series.mouseStrapPoints.push(
                _container.clientHeight - series.xAxis.defaltPadding
              )

              series.mouseStrapPoints.push(endX)
              series.mouseStrapPoints.push(
                _container.clientHeight - series.xAxis.defaltPadding
              )
              series.mouseStrapPoints.push(startX)
              series.mouseStrapPoints.push(
                _container.clientHeight - series.xAxis.defaltPadding
              )
              series.mouseStrapPoints.push(startX)
              series.mouseStrapPoints.push(series.xAxis.padding)
            } else if (series.dragType === 'measure') {
              const realStartY = _getRealYValueByYPixes(
                _container.clientHeight - startY,
                series
              )
              const realEndY = _getRealYValueByYPixes(
                _container.clientHeight - endY,
                series
              )
              // 需要将realX转化成真实时间戳
              const startidx = series.yAxis.interval[1] - realStartY
              const realstartYValue =
                series.yAxis.timeStamps[
                  series.yAxis.timeStamps.length - 1 - Math.round(startidx)
                ]

              const endidx = series.yAxis.interval[1] - realEndY
              const realEndYValue =
                series.yAxis.timeStamps[
                  series.yAxis.timeStamps.length - 1 - Math.round(endidx)
                ]
              // 判断是否打开了timemeasure 绘制矩形
              if (series.timeMeasureOpen) {
                series.timeMeasure = {
                  type: 'time',
                  startX: startX,
                  endX: endX,
                  startY: _container.clientHeight - startY,
                  endY: _container.clientHeight - endY,
                  words: [
                    {
                      x:
                        startX -
                        _textCtx.measureText(getHHmmssSSS(realstartYValue))
                          .width,
                      y: startY + 10,
                      str: getHHmmssSSS(realstartYValue)
                    },
                    {
                      x:
                        startX -
                        _textCtx.measureText(getHHmmssSSS(realEndYValue)).width,
                      y: endY,
                      str: getHHmmssSSS(realEndYValue)
                    }
                  ]
                }
              }
            }
          })
        }
        _refresh()
      } else {
        const x = event.offsetX
        const y = event.offsetY
        _isClickMarkLine = false
        _clickedMarkLine = null
        _clickedMarkLineSeries = null

        // 判断鼠标是否移动到了测量区域的四条边上
        const measureZoneFindResult = _findNearestMeasureZone(x, y)
        if (measureZoneFindResult) {
          if (measureZoneFindResult.direction === 'left') {
            _textcontainer.style.cursor = 'ew-resize'
          } else if (measureZoneFindResult.direction === 'right') {
            _textcontainer.style.cursor = 'ew-resize'
          } else if (measureZoneFindResult.direction === 'bottom') {
            _textcontainer.style.cursor = 'ns-resize'
          } else if (measureZoneFindResult.direction === 'top') {
            _textcontainer.style.cursor = 'ns-resize'
          } else if (measureZoneFindResult.direction === 'all') {
            _textcontainer.style.cursor = 'move'
          } else {
            _textcontainer.style.cursor = ''
          }
          _isClickMeasureZone = true
          _clickedMeasureZone = measureZoneFindResult
          _clickedMeasureZoneSeries = measureZoneFindResult.series
        } else {
          _isClickMeasureZone = false
          _clickedMeasureZone = null
          _clickedMeasureZoneSeries = null
        }

        // 判断鼠标是否移动到了测量区域中（拖动）
        const measureZoneDragResult = _findDragInMeasureZone(x, y)

        if (measureZoneDragResult) {
          if (measureZoneDragResult.direction === 'all') {
            _textcontainer.style.cursor = 'move'
          } else {
            _textcontainer.style.cursor = ''
          }
          _isClickToDragMeasureZone = true
          _clickedToDragMeasureZone = measureZoneDragResult
          // _clickedMeasureZoneSeries = measureZoneFindResult.series
          return
        } else {
          _isClickToDragMeasureZone = false
          _clickedToDragMeasureZone = null
          // _clickedMeasureZoneSeries = null
        }

        if (!_isClickMeasureZone && !_isClickToDragMeasureZone) {
          // 判断鼠标是否移动到了markLine上面
          const markFindResult = _findNearestMarkLine(x, y)

          if (markFindResult) {
            if (markFindResult.markLine.type === 'x') {
              _textcontainer.style.cursor = 'ew-resize'
            }
            if (markFindResult.markLine.type === 'y') {
              _textcontainer.style.cursor = 'ns-resize'
            }
            _isClickMarkLine = true
            _clickedMarkLine = markFindResult.markLine
            _clickedMarkLineSeries = markFindResult.series
          } else {
            _textcontainer.style.cursor = ''
            _isClickMarkLine = false
          }
        }
        if (
          !_isClickMeasureZone &&
          !_isClickToDragMeasureZone &&
          !_isClickMarkLine
        ) {
          // 判断当前是否移动到了yaxis左边的区域(需要)
          _isClickYaxisPadding = false

          _Series.forEach((series) => {
            if (_config.type === 'pubu') {
              // 瀑布流不判断y轴放大
              return
            }
            if (
              x < series.yAxis.padding &&
              _container.clientHeight - y > series.xAxis.padding &&
              _container.clientHeight - y <
                _container.clientHeight - series.xAxis.defaltPadding
            ) {
              _clickedYaxisSeries = series
              _isClickYaxisPadding = true
            }
          })
          if (_isClickYaxisPadding) {
            _textcontainer.style.cursor = 'pointer'
            return
          } else {
            _textcontainer.style.cursor = ''
          }

          if (!_isClickYaxisPadding) {
            // 判断当前是否移动到了xaxis下边的区域(需要)
            _isClickXaxisPadding = false

            _Series.forEach((series) => {
              if (_config.type === 'pubu') {
                // 瀑布流不判断y轴放大
                return
              }
              if (_container.clientHeight - y < series.xAxis.padding) {
                _clickedXaxisSeries = series
                _isClickXaxisPadding = true
              }
            })
            if (_isClickXaxisPadding) {
              _textcontainer.style.cursor = 'pointer'
              return
            } else {
              _textcontainer.style.cursor = ''
            }
          }
        }

        // 计算当前鼠标位置的xy值
        _Series.forEach((series) => {
          // 不能越过边界
          if (x < _Series[0].yAxis.padding) {
            return
          }
          if (x > _container.clientWidth - _Series[0].yAxis.defaltPadding) {
            return
          }
          if (y < _Series[0].xAxis.defaltPadding) {
            return
          }
          if (y > _container.clientHeight - _Series[0].xAxis.padding) {
            return
          }
          if (_config.type === 'line') {
            const realX = _getRealXValueByXPixes(x, series)
            // y坐标从下往上递增
            const realY = _getRealYValueByYPixes(
              _container.clientHeight - y,
              series
            )
            // 查看鼠标是否移动到y轴mark上了
            if (series.onMouseMoveListener) {
              series.onMouseMoveListener(realX, realY, event)
            }
          } else if (_config.type === 'pubu') {
            if (series.yAxis.timeStamps.length === 0) {
              return
            }
            const realX = _getRealXValueByXPixes(x, series)
            // y坐标从下往上递增
            const realY = _getRealYValueByYPixes(
              _container.clientHeight - y,
              series
            )
            // 查看鼠标是否移动到y轴mark上了
            // 需要将realX转化成真实时间戳
            const idx = series.yAxis.interval[1] - realY
            const realYValue =
              series.yAxis.timeStamps[
                series.yAxis.timeStamps.length - 1 - Math.round(idx)
              ]

            if (series.onMouseMoveListener) {
              series.onMouseMoveListener(realX, realYValue, event)
            }
          }
        })
      }
    }
  }

  function _doOnXIntervalChange (series, interval) {
    // 当坐标系变化的时候 重新计算一些数据
    if (series.kdCollectionOpen) {
      if (series.kdCollection) {
        const kdCollectionPositionValue =
          series.kdCollection.kdCollectionPositionValue
        const kdCollectionPosition = _getXPixesByXvalue(
          kdCollectionPositionValue,
          series
        )

        // //console.log("kdCollectionPositionValue:" +kdCollectionPositionValue)
        // //console.log("kdCollectionPosition:" +kdCollectionPosition)

        // //console.log((series.kdCollectionWidth/(series.xAxis.interval[1] - series.xAxis.interval[0])))
        const collectonZoneWidth =
          (series.kdCollectionWidth /
            (series.xAxis.interval[1] - series.xAxis.interval[0])) *
          (_container.clientWidth -
            series.yAxis.padding -
            series.yAxis.defaltPadding)

        // //console.log("collectonZoneWidth:" +collectonZoneWidth)
        series.kdCollection = {
          type: 'kdCollection',
          kdCollectionPosition: kdCollectionPosition,
          kdCollectionPositionValue: kdCollectionPositionValue,
          collectonZoneWidth: collectonZoneWidth,
          startX: kdCollectionPosition - collectonZoneWidth / 2,
          endX: kdCollectionPosition + collectonZoneWidth / 2,
          startY: series.xAxis.padding,
          endY: _container.clientHeight - series.xAxis.defaltPadding,
          points: [],
          words: []
        }
      }
    }
    // _refresh()
    if (series.xAxis.onXIntervalChange) {
      series.xAxis.onXIntervalChange(interval)
    }
  }

  function _doOnclick (event) {
    if (_onclickTimer) {
      clearTimeout(_onclickTimer)
      _onclickTimer = null
      // 已经是第二次点击了 直接执行
      _realDoOnclick(event)
    } else {
      // 已经是第一次点击了 设置定时任务
      _onclickTimer = setTimeout(() => {
        _realDoOnclick(event)
        _onclickTimer = null
      }, 100)
    }
  }

  function _realDoOnclick (event) {
    const x = event.offsetX
    const y = event.offsetY
    _Series.forEach((series) => {
      // 不能越过边界
      if (x < _Series[0].yAxis.padding) {
        return
      }
      if (x > _container.clientWidth - _Series[0].yAxis.defaltPadding) {
        return
      }
      if (y < _Series[0].xAxis.defaltPadding) {
        return
      }
      if (y > _container.clientHeight - _Series[0].xAxis.padding) {
        return
      }
      if (_config.type === 'line') {
        const realX = _getRealXValueByXPixes(x, series)
        // y坐标从下往上递增
        const realY = _getRealYValueByYPixes(
          _container.clientHeight - y,
          series
        )
        // 查看鼠标是否移动到y轴mark上了
        if (series.onclickListener) {
          series.onclickListener(realX, realY, event)
        }
      } else if (_config.type === 'pubu') {
        if (series.yAxis.timeStamps.length === 0) {
          return
        }
        const realX = _getRealXValueByXPixes(x, series)
        // y坐标从下往上递增
        const realY = _getRealYValueByYPixes(
          _container.clientHeight - y,
          series
        )
        // 查看鼠标是否移动到y轴mark上了
        // 需要将realX转化成真实时间戳
        const idx = series.yAxis.interval[1] - realY
        const realYValue =
          series.yAxis.timeStamps[
            series.yAxis.timeStamps.length - 1 - Math.round(idx)
          ]

        if (series.onclickListener) {
          series.onclickListener(realX, realYValue, event)
        }
      }
    })
  }

  function _findNearestMarkLine (x, y) {
    let result = null
    // 判断是否拉动markline
    let _nearestXMarkLineIndex = -1
    let finded = false
    _Series.forEach((series) => {
      // 判断是否在series范围内
      if (
        x < series.yAxis.padding ||
        x > _container.clientWidth - series.yAxis.defaltPadding ||
        y < series.xAxis.padding ||
        y > _container.clientHeight - series.xAxis.defaltPadding
      ) {
        return
      }
      // 如果已经判断点击了其他series的markline 就不计算当前的series里面的了
      if (finded) {
        return
      }
      series.xAxis.markLines.forEach((markLine, index) => {
        if (markLine.visible == false) {
          return
        }
        const distance = Math.abs(x - markLine.pixes)
        if (distance < 5) {
          finded = true
          if (_nearestXMarkLineIndex === -1) {
            _nearestXMarkLineIndex = index
            result = {
              markLine: markLine,
              series: series
            }
          } else {
            if (
              Math.abs(
                x - series.xAxis.markLines[_nearestXMarkLineIndex].pixes
              ) > Math.abs(x - markLine.pixes)
            ) {
              _nearestXMarkLineIndex = index
              result = {
                markLine: markLine,
                series: series
              }
            }
          }
        }
      })
      if (finded) {
        return
      }
      let _nearestYMarkLineIndex = -1
      series.yAxis.markLines.forEach((markLine, index) => {
        const distance = Math.abs(_container.clientHeight - y - markLine.pixes)
        if (distance < 5) {
          if (_nearestYMarkLineIndex === -1) {
            _nearestYMarkLineIndex = index
            result = {
              markLine: markLine,
              series: series
            }
          } else {
            if (
              Math.abs(
                _container.clientHeight -
                  y -
                  series.yAxis.markLines[_nearestYMarkLineIndex].pixes
              ) > Math.abs(_container.clientHeight - y - markLine.pixes)
            ) {
              _nearestYMarkLineIndex = index
              result = {
                markLine: markLine,
                series: series
              }
            }
          }
        }
      })
    })
    return result
  }

  function _findDragInMeasureZone (x, y) {
    let finded = false
    let result = null
    const yPixes = _container.clientHeight - y
    _Series.forEach((series) => {
      // 判断是否在series范围内
      if (
        x < series.yAxis.padding ||
        x > _container.clientWidth - series.yAxis.defaltPadding ||
        yPixes < series.xAxis.padding ||
        yPixes > _container.clientHeight - series.xAxis.defaltPadding
      ) {
        return
      }
      // 如果已经判断点击了其他series的measurezone 就不计算当前的series里面的了
      if (finded) {
        return
      }
      // 先判断SNRMeasure
      if (series.SNRMeasureOpen && series.SNRMeasure) {
        if (
          x < series.SNRMeasure.endX &&
          x > series.SNRMeasure.startX &&
          yPixes < series.SNRMeasure.endY &&
          yPixes > series.SNRMeasure.startY
        ) {
          finded = true
          result = {
            measureZone: series.SNRMeasure,
            series: series,
            direction: 'all'
          }
        }
      }
      if (finded) {
        return
      }
      // 再寻找 freqMeasure
      if (series.freqMeasureOpen && series.freqMeasure) {
        if (
          x < series.freqMeasure.endX &&
          x > series.freqMeasure.startX &&
          yPixes < series.freqMeasure.endY &&
          yPixes > series.freqMeasure.startY
        ) {
          finded = true
          result = {
            measureZone: series.freqMeasure,
            series: series,
            direction: 'all'
          }
        }
      }
      if (finded) {
        return
      }
      // 再寻找 freqMeasure
      if (series.timeMeasureOpen && series.timeMeasure) {
        if (
          x < series.timeMeasure.endX &&
          x > series.timeMeasure.startX &&
          yPixes < series.timeMeasure.endY &&
          yPixes > series.timeMeasure.startY
        ) {
          finded = true
          result = {
            measureZone: series.timeMeasure,
            series: series,
            direction: 'all'
          }
        }
      }
    })
    return result
  }

  /**
   * 寻找鼠标在哪个测量区域的边上
   * @param {*} x
   * @param {*} y
   * @returns
   */
  function _findNearestMeasureZone (x, y) {
    // 判断是否拉动markline
    let finded = false
    let result = null
    _Series.forEach((series) => {
      // 判断是否在series范围内
      if (
        x < series.yAxis.padding ||
        x > _container.clientWidth - series.yAxis.defaltPadding ||
        y < series.xAxis.padding ||
        y > _container.clientHeight - series.xAxis.defaltPadding
      ) {
        return
      }
      // 如果已经判断点击了其他series的measurezone 就不计算当前的series里面的了
      if (finded) {
        return
      }
      // 先判断SNRMeasure
      if (series.SNRMeasureOpen && series.SNRMeasure) {
        const xPixes = x
        const yPixes = _container.clientHeight - y
        // 判断是否在测量x轴的measurezone上
        let distance = 99999
        distance = Math.abs(yPixes - series.SNRMeasure.startY)
        if (
          distance < 5 &&
          x > series.SNRMeasure.startX &&
          x < series.SNRMeasure.endX
        ) {
          finded = true
          result = {
            measureZone: series.SNRMeasure,
            series: series,
            direction: 'bottom'
          }
        }
        distance = Math.abs(yPixes - series.SNRMeasure.endY)
        if (
          distance < 5 &&
          x > series.SNRMeasure.startX &&
          x < series.SNRMeasure.endX
        ) {
          finded = true
          result = {
            measureZone: series.SNRMeasure,
            series: series,
            direction: 'top'
          }
        }
        // distance = Math.abs(x - series.SNRMeasure.startX)
        // if(distance < 5 && (yPixes>series.SNRMeasure.startY && yPixes<series.SNRMeasure.endY)){
        //   finded = true
        //   result = {
        //     measureZone: series.SNRMeasure,
        //     series: series,
        //     direction: 'left'
        //   }
        // }
        // distance = Math.abs(x - series.SNRMeasure.endX)
        // if(distance < 5 && (yPixes>series.SNRMeasure.startY && yPixes<series.SNRMeasure.endY)){
        //   finded = true
        //   result = {
        //     measureZone: series.SNRMeasure,
        //     series: series,
        //     direction: 'right'
        //   }
        // }
      }
      if (result) {
        return
      }
      // 再寻找 freqMeasure
      if (series.freqMeasureOpen && series.freqMeasure) {
        const xPixes = x
        const yPixes = _container.clientHeight - y
        // 判断是否在测量x轴的measurezone上
        let distance = 99999
        distance = Math.abs(x - series.freqMeasure.startX)
        if (
          distance < 5 &&
          yPixes > series.freqMeasure.startY &&
          yPixes < series.freqMeasure.endY
        ) {
          finded = true
          result = {
            measureZone: series.freqMeasure,
            series: series,
            direction: 'left'
          }
        }
        distance = Math.abs(x - series.freqMeasure.endX)
        if (
          distance < 5 &&
          yPixes > series.freqMeasure.startY &&
          yPixes < series.freqMeasure.endY
        ) {
          finded = true
          result = {
            measureZone: series.freqMeasure,
            series: series,
            direction: 'right'
          }
        }
      }

      // 再寻找 kdCollection
      if (series.kdCollectionOpen && series.kdCollection) {
        const xPixes = x
        const yPixes = _container.clientHeight - y
        // 判断鼠标是否在采集区域内
        let distance = 99999
        distance = Math.abs(x - series.kdCollection.startX)
        if (
          series.kdCollection.startX < x &&
          x < series.kdCollection.endX &&
          series.kdCollection.startY < yPixes &&
          yPixes < series.kdCollection.endY
        ) {
          finded = true
          result = {
            measureZone: series.kdCollection,
            series: series,
            direction: 'all'
          }
        }
      }

      // 再寻找 timeMeasure
      if (series.timeMeasureOpen && series.timeMeasure) {
        const xPixes = x
        const yPixes = _container.clientHeight - y
        // 判断是否在测量y轴的timeMeasure上
        let distance = 99999
        distance = Math.abs(yPixes - series.timeMeasure.startY)
        if (
          distance < 5 &&
          x > series.timeMeasure.startX &&
          x < series.timeMeasure.endX
        ) {
          finded = true
          result = {
            measureZone: series.timeMeasure,
            series: series,
            direction: 'bottom'
          }
        }
        distance = Math.abs(yPixes - series.timeMeasure.endY)
        if (
          distance < 5 &&
          x > series.timeMeasure.startX &&
          x < series.timeMeasure.endX
        ) {
          finded = true
          result = {
            measureZone: series.timeMeasure,
            series: series,
            direction: 'top'
          }
        }
      }
    })
    return result
  }

  function getHHmmssSSS (time) {
    const date = new Date(time)
    const hour =
      date.getHours().toString().length > 1
        ? date.getHours()
        : '0' + date.getHours()
    const minutes =
      date.getMinutes().toString().length > 1
        ? date.getMinutes()
        : '0' + date.getMinutes()
    const seconds =
      date.getSeconds().toString().length > 1
        ? date.getSeconds()
        : '0' + date.getSeconds()
    const result =
      hour + ':' + minutes + ':' + seconds + '.' + date.getMilliseconds()
    return result
  }

  /**
   * 根据x轴的坐标值得到x轴的实际值(使用_axisMatrix的参考系,即边界为container内,方便进行坐标的计算)
   */
  function _getRealXValueByXPixes (x, series) {
    const percent =
      (x - series.yAxis.padding) /
      (_container.clientWidth -
        series.yAxis.padding -
        series.yAxis.defaltPadding)
    const result =
      (series.xAxis.interval[1] - series.xAxis.interval[0]) * percent +
      series.xAxis.interval[0]
    return result
  }
  /**
   * 根据y轴的坐标值得到y轴的实际值(使用_axisMatrix的参考系,即边界为container内,方便进行坐标的计算)
   */
  function _getRealYValueByYPixes (y, series) {
    const percent =
      (y - series.xAxis.padding) /
      (_container.clientHeight -
        series.xAxis.padding -
        series.xAxis.defaltPadding)
    const result =
      (series.yAxis.interval[1] - series.yAxis.interval[0]) * percent +
      series.yAxis.interval[0]
    return result
  }
  /**
   * 根据y的实际值得到y的坐标值(使用_axisMatrix的参考系,即边界为container内,方便进行坐标的计算)
   * @param {*} y
   */
  function _getYPixesByYvalue (y, series) {
    const yPercent =
      (y - series.yAxis.interval[0]) /
      (series.yAxis.interval[1] - series.yAxis.interval[0])
    // var transformedY = (_container.clientHeight - 50 - 10) * newYPercent
    const result =
      series.xAxis.padding +
      (_container.clientHeight -
        series.xAxis.padding -
        series.xAxis.defaltPadding) *
        yPercent
    return result
  }
  /**
   * 根据x的实际值得到x的坐标值(使用_axisMatrix的参考系,即边界为container内,方便进行坐标的计算)
   * @param {*} y
   */
  function _getXPixesByXvalue (x, series) {
    const xPercent =
      (x - series.xAxis.interval[0]) /
      (series.xAxis.interval[1] - series.xAxis.interval[0])
    // var transformedY = (_container.clientHeight - 50 - 10) * newYPercent
    const result =
      series.yAxis.padding +
      (_container.clientWidth -
        series.yAxis.padding -
        series.yAxis.defaltPadding) *
        xPercent
    return result
  }

  /**
   * 根据y的实际值得到y的坐标值(使用_lineMatrix的参考系,即边界为axis内部,方便进行坐标的计算)
   * @param {*} y
   */
  function _getYPixesByYvalueOnLineMatrix (y, series) {
    const yPercent =
      (y - series.yAxis.interval[0]) /
      (series.yAxis.interval[1] - series.yAxis.interval[0])
    // var transformedY = (_container.clientHeight - 50 - 10) * newYPercent
    const result =
      (_container.clientHeight -
        series.xAxis.padding -
        series.xAxis.defaltPadding) *
      yPercent
    return result
  }
  /**
   * 根据x的实际值得到x的坐标值(使用_lineMatrix的参考系,即边界为axis内部,方便进行坐标的计算)
   * @param {*} y
   */
  function _getXPixesByXvalueOnLineMatrix (x, series) {
    const xPercent =
      (x - series.xAxis.interval[0]) /
      (series.xAxis.interval[1] - series.xAxis.interval[0])
    // var transformedY = (_container.clientHeight - 50 - 10) * newYPercent
    const result =
      (_container.clientWidth -
        series.yAxis.padding -
        series.yAxis.defaltPadding) *
      xPercent
    return result
  }

  /**
   * 二分查找某个值所对应色带上的颜色
   * @param {*} colors
   * @param {*} val
   * @returns
   */
  function _searchColor (colors, val) {
    // let startPosition = 0
    // let endPosition = 0
    // for (let j = 0; j < colors.length; j++) {
    //   if (colors[j].value > val) {
    //     endPosition = j
    //     if (j - 1 > 0) {
    //       startPosition = j - 1
    //     } else {
    //       startPosition = 0
    //     }
    //     break
    //   }
    //   if (j === colors.length - 1) {
    //     startPosition = j
    //     endPosition = j
    //   }
    // }
    // return startPosition

    let left = 0
    let right = colors.length - 1
    let mid = 0

    while (left <= right) {
      mid = parseInt(left + (right - left) / 2) // 计算中间元素的索引
      if (colors[mid].value < val) {
        left = mid + 1 // 目标值在右半部分
      } else {
        right = mid - 1 // 目标值在左半部分
      }
    }
    return mid
  }

  function _getRGB (colors, val) {
    const temObj = {
      r: 255,
      g: 0,
      b: 0
    }
    console.log(colors)
    /* colors.some((item, index) => {
      if (index !== colors.length - 1 && val > item.value) {
        const persent = ((val - item.value) / (colors[index + 1].value - item.value))
        temObj.r = (colors[index + 1].color.r - item.color.r) * persent
        temObj.g = (colors[index + 1].color.g - item.color.g) * persent
        temObj.b = (colors[index + 1].color.b - item.color.b) * persent
        return true
      } else if (index === colors.length - 1 && val > item.value) {
        const persent = ((val - item.value) / (item.value - colors[index - 1].value))
      }
    }) */

    return temObj
  }

  return {
    /**
     * 罗盘图
     */
    compass (config) {
      _config = {
        type: 'compass',
        container: config.container,
        background: config.background
          ? config.background
          : {
              r: 0,
              g: 0,
              b: 0
            }
      }
      _compassConfig.wordColor = config.wordColor
        ? config.wordColor
        : {
            r: 1,
            g: 1,
            b: 1
          }
      _initGl()
      _addCompassMouseEventListener()
      return {
        refresh () {
          _refresh()
        },
        setMeasureListener (listener) {
          _compassConfig.compassMeasureListener = listener
        },
        setPointAngle (angle) {
          _compassConfig.compassPointRotation = (angle / 360) * 2 * Math.PI
          _compassConfig.compassPointOldRotation =
            _compassConfig.compassPointRotation
          _refresh()
        },
        setPoints (data) {
          if (data && data.length > 0) {
            const tmpPoints = []
            const tmpPointSizes = []
            const banjing = _container.clientHeight / 2 - 5
            data.forEach((item) => {
              const theta = (item.angle * Math.PI) / 180
              const x1 = 0 + item.amplitude * banjing * Math.sin(theta)
              const y1 = 0 + item.amplitude * banjing * Math.cos(theta)
              // tmpPoints = tmpPoints.concat([x1, y1])
              // tmpPoints.push({
              //   x: x1,
              //   y: y1
              // })
              tmpPoints.push({
                x: x1,
                y: y1,
                xToRect: 0,
                yToRect: banjing * item.amplitude,
                angle: item.angle,
                color: item.color ? item.color : { r: 0, g: 1, b: 1 }
              })
              tmpPointSizes.push(5)
            })
            _compassConfig.comapssPoints = tmpPoints
            _compassConfig.comapssPointsSizes = tmpPointSizes
            // 重新计算点坐标
            _compassConfig.comapssShowPoints = []
            _refresh()
          }
        },
        setConfidence (confidence) {
          _compassConfig.confidence = confidence
          _refresh()
        },
        setPointSize (pointSize) {
          _compassConfig.pointSize = pointSize
          _refresh()
        },
        setCarPositionRotation (angle) {
          _compassConfig.compassCarPositionRotation =
            (angle / 360) * 2 * Math.PI
          _compassConfig.compassCarPositionMatrix = null
        },
        setCompassScaleRotation (angle) {
          _compassConfig.compassScaleRotation = (angle / 360) * 2 * Math.PI
          _compassConfig.compassMatrix = null
          _compassConfig.compassPointMatrix = null
        },
        // 清空数据
        clear () {
          _compassConfig.confidence = null
          _compassConfig.comapssPoints = []
          _compassConfig.comapssPointsSizes = []
          _compassConfig.comapssShowPoints = []
          _compassConfig.compassPointRotation = null
          _compassConfig.compassPointOldRotation = null
          _compassConfig.pointShowJiaoDuChange = null
          _refresh()
        },
        reSize () {
          const div = document.querySelector('#' + _config.container)
          _container.width = div.clientWidth
          _container.height = div.clientHeight
          _textCtx.width = div.clientWidth
          _textCtx.height = div.clientHeight
          _clearCaculatedData()
          _refresh()
        }
      }
    },
    /**
     * 瀑布图
     */
    pubu (config) {
      _config = {
        type: 'pubu',
        container: config.container,
        background:
          config.background != null
            ? config.background
            : {
                r: 0,
                g: 0,
                b: 0
              }
      }
      _initGl()
      _addMouseEventListener()
      return {
        addSeries (seriesConfig) {
          if (!seriesConfig) {
            seriesConfig = {
              xAxisInterval: [0, 100],
              xAxisPadding: 30,
              xAxisAnotherPadding: 10,
              xAxisMarkNum: 5,
              yAxisInterval: [0, seriesConfig.row],
              yAxisPadding: 30,
              yAxisAnotherPadding: 30,
              yAxisMarkNum: 5,
              column: 1024,
              row: 60,
              direction: 'topToBottom',
              axisColor: {
                r: 1,
                g: 1,
                b: 1,
                a: 1
              },
              showColors: false,
              timeStampFormatter: 'hh:mm:ss',
              // 瀑布图是否展示全部数据（是的话不处理x轴偏移量）
              showAllData: false,
              measureTextColor: {
                r: 1,
                g: 1,
                b: 1,
                a: 1
              }
            }
          } else {
            seriesConfig = {
              title: seriesConfig.title
                ? seriesConfig.title
                : { text: '', top: 0, left: 0 },
              axisXUnits: seriesConfig.axisXUnits
                ? seriesConfig.axisXUnits
                : { text: '', top: 0, left: 0 },
              axisYUnits: seriesConfig.axisYUnits
                ? seriesConfig.axisYUnits
                : { text: '', top: 0, left: 0 },
              tooltip: seriesConfig.tooltip
                ? seriesConfig.tooltip
                : { value1: '', value2: '', top: 0, left: 0 },
              xAxisInterval: seriesConfig.xAxisInterval
                ? seriesConfig.xAxisInterval
                : [0, 100],
              xAxisPadding: seriesConfig.xAxisPadding
                ? seriesConfig.xAxisPadding
                : 30,
              xAxisAnotherPadding:
                seriesConfig.xAxisAnotherPadding != null
                  ? seriesConfig.xAxisAnotherPadding
                  : 30,
              xAxisMarkNum: seriesConfig.xAxisMarkNum
                ? seriesConfig.xAxisMarkNum
                : 5,
              xAxisMarkFormatter: seriesConfig.xAxisMarkFormatter,
              yAxisInterval: [-seriesConfig.row, 0],
              yAxisPadding: seriesConfig.yAxisPadding
                ? seriesConfig.yAxisPadding
                : 30,
              yAxisAnotherPadding: seriesConfig.yAxisAnotherPadding
                ? seriesConfig.yAxisAnotherPadding
                : 30,
              yAxisMarkNum: seriesConfig.yAxisMarkNum
                ? seriesConfig.yAxisMarkNum
                : 5,
              yAxisMarkFormatter: seriesConfig.yAxisMarkFormatter,
              minXInterval: seriesConfig.minXInterval,
              column: seriesConfig.column,
              row: seriesConfig.row,
              direction: seriesConfig.direction
                ? seriesConfig.direction
                : 'topToBottom',
              axisColor: seriesConfig.axisColor
                ? seriesConfig.axisColor
                : {
                    r: 1,
                    g: 1,
                    b: 1,
                    a: 1
                  },
              showColors: seriesConfig.showColors
                ? seriesConfig.showColors
                : false,
              timeStampFormatter: seriesConfig.timeStampFormatter
                ? seriesConfig.timeStampFormatter
                : 'hh:mm:ss',
              showAllData: seriesConfig.showAllData
                ? seriesConfig.showAllData
                : false,
              measureTextColor: seriesConfig.measureTextColor
                ? seriesConfig.measureTextColor
                : {
                    r: 1,
                    g: 1,
                    b: 1,
                    a: 1
                  }
            }
          }
          const newSeries = {
            title: seriesConfig.title,
            axisXUnits: seriesConfig.axisXUnits,
            axisYUnits: seriesConfig.axisYUnits,
            tooltip: seriesConfig.tooltip,
            direction: seriesConfig.direction,
            column: seriesConfig.column ? seriesConfig.column : 1024,
            row: seriesConfig.row ? seriesConfig.row : 60,
            xAxis: {
              interval: seriesConfig.xAxisInterval,
              oldInterval: [
                seriesConfig.xAxisInterval[0],
                seriesConfig.xAxisInterval[1]
              ],
              padding: seriesConfig.xAxisPadding,
              defaltPadding: seriesConfig.xAxisAnotherPadding,
              markNum: seriesConfig.xAxisMarkNum, // 刻度数量
              xAxisMarkFormatter: seriesConfig.xAxisMarkFormatter,
              minXInterval: seriesConfig.minXInterval,
              color: {
                r: seriesConfig.axisColor.r,
                g: seriesConfig.axisColor.g,
                b: seriesConfig.axisColor.b,
                a: seriesConfig.axisColor.a
              },
              points: [],
              words: [],
              markLines: [],
              markZones: [],
              markZonesHighLight: [],
              markZonesOfBlackList: [],
              markZonePoints: [],
              markZonePointColors: []
            },
            yAxis: {
              interval: seriesConfig.yAxisInterval,
              padding: seriesConfig.yAxisPadding,
              defaltPadding: seriesConfig.yAxisAnotherPadding,
              markNum: seriesConfig.yAxisMarkNum,
              yAxisMarkFormatter: (value) => {
                // seriesConfig.yAxisMarkFormatter,
                if (Math.round(value) < 0) {
                  return ''
                }
                const index = newSeries.yAxis.interval[1] - Math.round(value)

                if (
                  index > newSeries.yAxis.timeStamps.length ||
                  newSeries.yAxis.timeStamps.length === 0
                ) {
                  return ''
                }
                const timeStamp =
                  newSeries.yAxis.timeStamps[
                    newSeries.yAxis.timeStamps.length - 1 - index
                  ]

                if (!timeStamp) {
                  return ''
                }
                if (seriesConfig.timeStampFormatter === 'hh:mm:ss') {
                  const date = new Date(timeStamp)
                  const hour =
                    date.getHours().toString().length > 1
                      ? date.getHours()
                      : '0' + date.getHours()
                  const minutes =
                    date.getMinutes().toString().length > 1
                      ? date.getMinutes()
                      : '0' + date.getMinutes()
                  const seconds =
                    date.getSeconds().toString().length > 1
                      ? date.getSeconds()
                      : '0' + date.getSeconds()
                  return hour + ':' + minutes + ':' + seconds
                } else if (seriesConfig.timeStampFormatter === 'mm:ss') {
                  const date = new Date(timeStamp)
                  const minutes =
                    date.getMinutes().toString().length > 1
                      ? date.getMinutes()
                      : '0' + date.getMinutes()
                  const seconds =
                    date.getSeconds().toString().length > 1
                      ? date.getSeconds()
                      : '0' + date.getSeconds()
                  return minutes + ':' + seconds
                }
              },
              color: {
                r: seriesConfig.axisColor.r,
                g: seriesConfig.axisColor.g,
                b: seriesConfig.axisColor.b,
                a: seriesConfig.axisColor.a
              },
              timeStamps: [],
              points: [],
              words: [],
              markLines: []
            },
            color: {
              r: 0,
              g: 1,
              b: 0,
              a: 1
            },
            // 折线数据
            lines: [],
            dragType: 'zoom',
            rectMarkZone: [],
            rectMarkZonepoints: [],
            timeMeasureOpen: false,
            timeMeasure: null,
            // 最小值
            min: 0,
            // 最大值
            max: 255,
            // 色带
            waterColors: null,
            showColors: seriesConfig.showColors,
            showAllData: seriesConfig.showAllData,
            measureTextColor: seriesConfig.measureTextColor,
            // 是否允许缩放
            allowZoom: true
          }
          _Series.push(newSeries)

          return {
            changeShowAllData (bool) {
              newSeries.showAllData = bool
            },
            addTooltip (tooltip) {
              newSeries.tooltip = tooltip
            },
            setColumn (newColumn) {
              const imageNum = parseInt(newColumn / _maxPointNum) + 1

              newSeries.column = newColumn

              const imageColumnPerImage = parseInt(newColumn / imageNum)

              let tmp = 0
              _imageList = []
              for (let i = 0; i < imageNum; i++) {
                let imageColumn = imageColumnPerImage
                if (i == imageNum - 1) {
                  imageColumn = newColumn - tmp
                }
                tmp += imageColumnPerImage
                const Unit8Num = newSeries.row * imageColumn * 4
                const imageDataUnit8 = new Uint8Array(Unit8Num)

                for (let i = 0; i < newSeries.row * imageColumn; i++) {
                  imageDataUnit8[i * 4] = 0
                  imageDataUnit8[i * 4 + 1] = 0
                  imageDataUnit8[i * 4 + 2] = 0
                  imageDataUnit8[i * 4 + 3] = 255
                }
                _imageList.push({
                  imageDataUnit8: imageDataUnit8,
                  imageColumn: imageColumn
                })
              }
            },
            setXAxisMarkFormatter (newXAxisMarkFormatter) {
              newSeries.xAxis.xAxisMarkFormatter = newXAxisMarkFormatter
              _clearCaculatedData()
            },
            setOnClickListener (listener) {
              newSeries.onclickListener = listener
            },
            setOnMouseMoveListener (listener) {
              newSeries.onMouseMoveListener = listener
            },
            setOnMeasureListener (listener) {
              newSeries.onMeasureListener = listener
            },
            addRowData (row, timeStamp) {
              newSeries.yAxis.timeStamps.push(timeStamp)
              newSeries.data = row
              if (newSeries.timeMeasureOpen && newSeries.timeMeasure) {
                newSeries.timeMeasure.words = []
              }
              if (newSeries.yAxis.timeStamps.length > newSeries.row + 1) {
                newSeries.yAxis.timeStamps.splice(0, 1)
              }
              if (!newSeries.colors) {
                newSeries.colors = [
                  {
                    value: 0,
                    color: { r: 0, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (1 / 5),
                    color: { r: 51, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (2 / 5),
                    color: { r: 89, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (3 / 5),
                    color: { r: 89, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (4 / 5),
                    color: { r: 142, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (5 / 5),
                    color: { r: 255, g: 0, b: 0 }
                  }
                ]
              }
              // 填充图片数据
              _imageList.forEach((image, index) => {
                const colors = newSeries.colors
                // 新一行的数据 （图片cloumn数量乘以4）
                const newData = new Uint8Array(image.imageColumn * 4)
                const startNum = index * image.imageColumn * 2

                const endNum = startNum + image.imageColumn * 2
                // console.log("从" + startNum + "开始读取到" + endNum)
                for (let i = startNum; i < endNum; i += 2) {
                  const x = row[i]
                  const y = row[i + 1]
                  // 计算颜色

                  // 计算颜色
                  const startPosition = _searchColor(colors, y)
                  // const temRGB = _getRGB(colors, y)
                  const pos = (i / 2 - startNum / 2) * 4
                  const pos2 = (i / 2 - startNum / 2) * 4 + 1
                  const pos3 = (i / 2 - startNum / 2) * 4 + 2
                  const pos4 = (i / 2 - startNum / 2) * 4 + 3
                  if (y === -1) {
                    newData[pos] = 0
                    newData[pos2] = 0
                    newData[pos3] = 0
                    newData[pos4] = 255
                  } else {
                    newData[pos] = colors[startPosition].color.r
                    newData[pos2] = colors[startPosition].color.g
                    newData[pos3] = colors[startPosition].color.b
                    newData[pos4] = 255
                    /* newData[pos] = temRGB.r
                    newData[pos2] = temRGB.g
                    newData[pos3] = temRGB.b
                    newData[pos4] = 255 */
                  }
                }
                // 后移
                image.imageDataUnit8.copyWithin(
                  image.imageColumn * 4,
                  -(newSeries.row * image.imageColumn * 4),
                  -image.imageColumn * 4
                )
                // 将第一行的数据放入
                image.imageDataUnit8.set(newData, 0)
              })

              // y坐标加一
              newSeries.yAxis.interval[0] = newSeries.yAxis.interval[0] + 1
              newSeries.yAxis.interval[1] = newSeries.yAxis.interval[1] + 1
              if (newSeries.direction === 'topToBottom') {
                newSeries.yAxis.points = []
                newSeries.yTablePoints = []
              }
              if (newSeries.direction === 'rightToLeft') {
                newSeries.xAxis.points = []
                newSeries.xTablePoints = []
              }
              newSeries.rectMarkZonepoints = []
              // newSeries.rectMarkZone.forEach((markZone) => {
              //   markZone.transformedData = []
              // })
            },
            getYData (x) {
              const lineData = newSeries.data
              let y = null
              // 计算索引 => 更新了算法，占的比例不应该是点数的，而应该是间隔数的
              if (lineData.length && lineData.length > 0) {
                const index = Number(
                  (
                    ((x - lineData[0]) /
                      (lineData[lineData.length - 2] - lineData[0])) *
                    (lineData.length / 2 - 1)
                  ).toFixed(0)
                )
                y = lineData[2 * index + 1]
              }
              if (isNaN(y)) y = null
              return y
            },
            addRowDataNoXData (row, timeStamp) {
              newSeries.yAxis.timeStamps.push(timeStamp)
              newSeries.data = row
              if (newSeries.timeMeasureOpen && newSeries.timeMeasure) {
                newSeries.timeMeasure.words = []
              }
              if (newSeries.yAxis.timeStamps.length > newSeries.row + 1) {
                newSeries.yAxis.timeStamps.splice(0, 1)
              }
              if (!newSeries.colors) {
                newSeries.colors = [
                  {
                    value: 0,
                    color: { r: 0, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (1 / 5),
                    color: { r: 51, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (2 / 5),
                    color: { r: 89, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (3 / 5),
                    color: { r: 89, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (4 / 5),
                    color: { r: 142, g: 0, b: 0 }
                  },
                  {
                    value: 255 * (5 / 5),
                    color: { r: 255, g: 0, b: 0 }
                  }
                ]
              }
              // 填充图片数据
              _imageList.forEach((image, index) => {
                const colors = newSeries.colors
                // 新一行的数据 （图片cloumn数量乘以4）
                const newData = new Uint8Array(image.imageColumn * 4)
                const startNum = index * image.imageColumn

                const endNum = startNum + image.imageColumn
                // console.log("从" + startNum + "开始读取到" + endNum)
                for (let i = startNum; i < endNum; i++) {
                  const y = row[i]
                  // 计算颜色

                  // 计算颜色
                  const startPosition = _searchColor(colors, y)
                  const pos = (i - startNum) * 4
                  const pos2 = (i - startNum) * 4 + 1
                  const pos3 = (i - startNum) * 4 + 2
                  const pos4 = (i - startNum) * 4 + 3
                  if (y === -1) {
                    newData[pos] = 0
                    newData[pos2] = 0
                    newData[pos3] = 0
                    newData[pos4] = 255
                  } else {
                    newData[pos] = colors[startPosition].color.r
                    newData[pos2] = colors[startPosition].color.g
                    newData[pos3] = colors[startPosition].color.b
                    newData[pos4] = 255
                  }
                }
                // 后移
                image.imageDataUnit8.copyWithin(
                  image.imageColumn * 4,
                  -(newSeries.row * image.imageColumn * 4),
                  -image.imageColumn * 4
                )
                // 将第一行的数据放入
                image.imageDataUnit8.set(newData, 0)
              })

              // y坐标加一
              newSeries.yAxis.interval[0] = newSeries.yAxis.interval[0] + 1
              newSeries.yAxis.interval[1] = newSeries.yAxis.interval[1] + 1
              if (newSeries.direction === 'topToBottom') {
                newSeries.yAxis.points = []
                newSeries.yTablePoints = []
              }
              if (newSeries.direction === 'rightToLeft') {
                newSeries.xAxis.points = []
                newSeries.xTablePoints = []
              }
              newSeries.rectMarkZonepoints = []
              // newSeries.rectMarkZone.forEach((markZone) => {
              //   markZone.transformedData = []
              // })
            },
            /**
             * 清空数据
             */
            clearData () {
              _imageList.forEach((image) => {
                const Unit8Num = newSeries.row * image.imageColumn * 4
                image.imageDataUnit8 = new Uint8Array(Unit8Num)
                for (let i = 0; i < newSeries.row * image.imageColumn; i++) {
                  image.imageDataUnit8[i * 4] = 0
                  image.imageDataUnit8[i * 4 + 1] = 0
                  image.imageDataUnit8[i * 4 + 2] = 0
                  image.imageDataUnit8[i * 4 + 3] = 255
                }
              })
              newSeries.yAxis.timeStamps = []
              newSeries.yAxis.interval = [-seriesConfig.row, 0]
              _clearCaculatedData()
              _refresh()
            },
            /**
             * 设置最大最小value(影响颜色)
             */
            setValueInterval (min, max) {
              newSeries.min = min
              newSeries.max = max
              if (!newSeries.waterColors) {
                const tmp = []
                const zcColors = waterColor.zcColors()
                for (let i = 0; i < zcColors.length; i++) {
                  tmp.push(zcColors[zcColors.length - 1 - i])
                }
                newSeries.waterColors = tmp
              }
              const interval = newSeries.max - newSeries.min
              const colors = []
              newSeries.waterColors.forEach((waterColor, index) => {
                colors.push({
                  value:
                    min + interval * (index / newSeries.waterColors.length),
                  color: {
                    r: waterColor.R,
                    g: waterColor.G,
                    b: waterColor.B
                  }
                })
              })
              newSeries.colors = colors
            },
            setMaxXInterval (newInterval) {
              newSeries.xAxis.interval = [newInterval[0], newInterval[1]]
              newSeries.xAxis.oldInterval = [newInterval[0], newInterval[1]]
              _clearCaculatedData()
            },
            changeXInterval (newInterval) {
              newSeries.xAxis.interval = newInterval
              _clearCaculatedData()
            },
            setOnXIntervalChange (listener) {
              newSeries.xAxis.onXIntervalChange = listener
            },
            addRectMarkZone (startX, endX, startY, endY, str) {
              // 传入的是时间戳,需要转化成坐标
              let realStartY = -1
              for (let i = 0; i < newSeries.yAxis.timeStamps.length; i++) {
                if (startY < newSeries.yAxis.timeStamps[i]) {
                  if (i - 1 >= 0) {
                    realStartY = i - 1
                  }
                  break
                }
              }
              let realEndY = -1
              for (let i = 0; i < newSeries.yAxis.timeStamps.length; i++) {
                if (endY < newSeries.yAxis.timeStamps[i]) {
                  if (i - 1 >= 0) {
                    realEndY = i - 1
                  }
                  break
                }
              }
              if (realStartY < 0 || realEndY < 0) {
                return
              }
              // 之前的值只表示y坐标在axis.row中的排名位置 所以需要加上interval[0],算出实际value
              realStartY = newSeries.yAxis.interval[0] + realStartY
              realEndY = newSeries.yAxis.interval[0] + realEndY
              newSeries.rectMarkZone.push({
                startX: startX,
                endX: endX,
                startY: realStartY,
                endY: realEndY,
                str: str,
                // startY: startY,
                // endY: endY,
                transformedData: []
              })
              // newSeries.rectMarkZonepoints = []
            },
            clearRectMarkZone () {
              newSeries.rectMarkZone = []
              newSeries.rectMarkZonepoints = []
            },
            changeDrageType (type) {
              if (type === 'zoom' || type === 'measure') {
                newSeries.dragType = type
              }
            },
            setTimeMeasureOpen (timeMeasureOpen) {
              if (timeMeasureOpen) {
                // newSeries.dragType = 'measure'
                newSeries.dragType = 'zoom'
                newSeries.timeMeasureOpen = timeMeasureOpen
                // 打开时间测量的时候框选一个默认区域
                if (newSeries.timeMeasure) {
                  return
                }
                const startX = _container.clientWidth / 2 - 50
                const endX = _container.clientWidth / 2 + 50
                const startY = _container.clientHeight / 2 - 50
                const endY = _container.clientHeight / 2 + 50

                const realStartX = _getRealXValueByXPixes(startX, newSeries)
                const realStartY = _getRealYValueByYPixes(startY, newSeries)

                const realEndX = _getRealXValueByXPixes(endX, newSeries)
                const realEndY = _getRealYValueByYPixes(endY, newSeries)
                // 需要将realX转化成真实时间戳
                const startidx = newSeries.yAxis.interval[1] - realStartY
                const realYrealStartYValue =
                  newSeries.yAxis.timeStamps[
                    newSeries.yAxis.timeStamps.length - 1 - Math.round(startidx)
                  ]

                const endidx = newSeries.yAxis.interval[1] - realEndY
                const realEndYValue =
                  newSeries.yAxis.timeStamps[
                    newSeries.yAxis.timeStamps.length - 1 - Math.round(endidx)
                  ]
                // 计算时间
                newSeries.timeMeasure = {
                  type: 'time',
                  startX: startX,
                  endX: endX,
                  startY: startY,
                  endY: endY,
                  words: [
                    {
                      x:
                        startX -
                        _textCtx.measureText(getHHmmssSSS(realYrealStartYValue))
                          .width,
                      y: startY + 10,
                      str: getHHmmssSSS(realYrealStartYValue)
                    },
                    {
                      x:
                        startX -
                        _textCtx.measureText(getHHmmssSSS(realEndYValue)).width,
                      y: endY,
                      str: getHHmmssSSS(realEndYValue)
                    }
                  ]
                }
              } else {
                newSeries.dragType = 'zoom'
                newSeries.timeMeasureOpen = timeMeasureOpen
              }
            },
            setColors (waterColors) {
              const interval = newSeries.max - newSeries.min
              const tmp = []
              for (let i = 0; i < waterColors.length; i++) {
                tmp.push(waterColors[waterColors.length - 1 - i])
              }
              newSeries.waterColors = tmp
              const colors = []
              newSeries.waterColors.forEach((waterColor, index) => {
                colors.push({
                  value:
                    newSeries.min + interval * (index / waterColors.length),
                  color: {
                    r: waterColor.R / 255,
                    g: waterColor.G / 255,
                    b: waterColor.B / 255
                  }
                })
              })
              newSeries.colors = colors
            },
            setAllowZoom (allowZoom) {
              newSeries.allowZoom = allowZoom
            }
          }
        },
        /**
         * 刷新当前图表
         */
        refresh () {
          _refresh()
        },
        reSize () {
          const div = document.querySelector('#' + _config.container)
          _container.width = div.clientWidth
          _container.height = div.clientHeight
          _textcontainer.width = div.clientWidth
          _textcontainer.height = div.clientHeight
          _textCtx.width = div.clientWidth
          _textCtx.height = div.clientHeight
          _clearCaculatedData()
          // 清空计算矩阵
          _axisMatrix = null
          _Series.forEach((series) => {
            series._linesMatrix = null
            // 清空axis标记  的文字缓存
            series.xAxis.points = []
            series.yAxis.points = []
          })
          _refresh()
        }
      }
    },
    /**
     * 折线图
     */
    lineChart (config) {
      _config = {
        type: 'line',
        container: config.container,
        background:
          config.background != null
            ? config.background
            : {
                r: 0,
                g: 0,
                b: 0
              }
      }
      _initGl()
      // 添加鼠标监听
      _addMouseEventListener()
      return {
        /**
         * 添加新的线
         * seriesConfig
         *
         */
        addSeries (seriesConfig) {
          if (!seriesConfig) {
            seriesConfig = {
              xAxisInterval: [0, 100],
              xAxisPadding: 30,
              xAxisAnotherPadding: 10,
              xAxisMarkNum: 5,
              yAxisInterval: [0, 100],
              yAxisPadding: 30,
              yAxisAnotherPadding: 30,
              yAxisMarkNum: 5,
              axisColor: {
                r: 1,
                g: 1,
                b: 1,
                a: 1
              },
              measureTextColor: {
                r: 1,
                g: 1,
                b: 1,
                a: 1
              },
              showMarkZoneWord: true
            }
          } else {
            seriesConfig = {
              title: seriesConfig.title
                ? seriesConfig.title
                : { text: '', top: 0, left: 0 },
              axisXUnits: seriesConfig.axisXUnits
                ? seriesConfig.axisXUnits
                : { text: '', top: 0, left: 0 },
              axisYUnits: seriesConfig.axisYUnits
                ? seriesConfig.axisYUnits
                : { text: '', top: 0, left: 0 },
              tooltip: seriesConfig.tooltip
                ? seriesConfig.tooltip
                : { value1: '', value2: '', top: 0, left: 0 },
              xAxisInterval: seriesConfig.xAxisInterval
                ? seriesConfig.xAxisInterval
                : [0, 100],
              xAxisPadding: seriesConfig.xAxisPadding
                ? seriesConfig.xAxisPadding
                : 30,
              xAxisAnotherPadding:
                seriesConfig.xAxisAnotherPadding != null
                  ? seriesConfig.xAxisAnotherPadding
                  : 30,
              xAxisMarkNum: seriesConfig.xAxisMarkNum
                ? seriesConfig.xAxisMarkNum
                : 5,
              xAxisMarkFormatter: seriesConfig.xAxisMarkFormatter,
              yAxisInterval: seriesConfig.yAxisInterval
                ? seriesConfig.yAxisInterval
                : [0, 100],
              yAxisPadding: seriesConfig.yAxisPadding
                ? seriesConfig.yAxisPadding
                : 30,
              yAxisAnotherPadding: seriesConfig.yAxisAnotherPadding
                ? seriesConfig.yAxisAnotherPadding
                : 30,
              yAxisMarkNum: seriesConfig.yAxisMarkNum
                ? seriesConfig.yAxisMarkNum
                : 5,
              yAxisMarkFormatter: seriesConfig.yAxisMarkFormatter,
              minXInterval: seriesConfig.minXInterval,
              axisColor: seriesConfig.axisColor
                ? seriesConfig.axisColor
                : {
                    r: 1,
                    g: 1,
                    b: 1,
                    a: 1
                  },
              measureTextColor: seriesConfig.measureTextColor
                ? seriesConfig.measureTextColor
                : {
                    r: 1,
                    g: 1,
                    b: 1,
                    a: 1
                  },
              showMarkZoneWord:
                seriesConfig.showMarkZoneWord != null
                  ? seriesConfig.showMarkZoneWord
                  : true
            }
          }
          const newSeries = {
            title: seriesConfig.title,
            axisXUnits: seriesConfig.axisXUnits,
            axisYUnits: seriesConfig.axisYUnits,
            tooltip: seriesConfig.tooltip,
            xAxis: {
              interval: seriesConfig.xAxisInterval,
              oldInterval: [
                seriesConfig.xAxisInterval[0],
                seriesConfig.xAxisInterval[1]
              ],
              padding: seriesConfig.xAxisPadding,
              defaltPadding: seriesConfig.xAxisAnotherPadding,
              markNum: seriesConfig.xAxisMarkNum, // 刻度数量
              xAxisMarkFormatter: seriesConfig.xAxisMarkFormatter,
              minXInterval: seriesConfig.minXInterval,
              color: {
                r: seriesConfig.axisColor.r,
                g: seriesConfig.axisColor.g,
                b: seriesConfig.axisColor.b,
                a: seriesConfig.axisColor.a
              },
              points: [],
              words: [],
              markLines: [],
              markZones: [],
              markZonesHighLight: [],
              markZonesOfBlackList: [],
              showMarkZoneWord: seriesConfig.showMarkZoneWord
            },
            yAxis: {
              interval: seriesConfig.yAxisInterval,
              oldInterval: [
                seriesConfig.yAxisInterval[0],
                seriesConfig.yAxisInterval[1]
              ],
              padding: seriesConfig.yAxisPadding,
              defaltPadding: seriesConfig.yAxisAnotherPadding,
              markNum: seriesConfig.yAxisMarkNum,
              yAxisMarkFormatter: seriesConfig.yAxisMarkFormatter,
              color: {
                r: seriesConfig.axisColor.r,
                g: seriesConfig.axisColor.g,
                b: seriesConfig.axisColor.b,
                a: seriesConfig.axisColor.a
              },
              points: [],
              words: [],
              markLines: []
            },
            color: {
              r: 0,
              g: 1,
              b: 0,
              a: 1
            },
            // 折线数据
            lines: [],
            dragType: 'zoom',
            SNRMeasureOpen: false,
            SNRMeasure: null,
            freqMeasureOpen: false,
            freqMeasure: null,
            kdSelectOpen: false,
            kdSelect: null,
            kdCollectionWidth: 100,
            measureTextColor: seriesConfig.measureTextColor,
            // 是否允许缩放
            allowZoom: true
          }
          _Series.push(newSeries)
          const throttleOnXIntervalChange = throttle(() => {
            // if(newSeries.xAxis.onXIntervalChange){
            _doOnXIntervalChange(newSeries, [
              newSeries.xAxis.interval[0],
              newSeries.xAxis.interval[1]
            ])
            // }
          }, 100)
          newSeries.throttleOnXIntervalChange = throttleOnXIntervalChange
          return {
            addLine (lineConfig) {
              if (!lineConfig) {
                lineConfig = {
                  color: {
                    r: 1,
                    g: 1,
                    b: 1
                  }
                }
              }
              const newLine = {
                data: [],
                transferedData: [],
                color: {
                  r: lineConfig.color.r,
                  g: lineConfig.color.g,
                  b: lineConfig.color.b,
                  a: 1
                },
                visible: true
              }
              newSeries.lines.push(newLine)
              return {
                setData (newData) {
                  newLine.data = newData
                  newLine.transferedData = []
                },
                setVisible (visible) {
                  newLine.visible = visible
                },
                // 扫频数据用于计算X坐标对应的Y值
                getYData (x, index) {
                  /* const temIndex = index || 0
                  const lineData = _Series[0].lines[temIndex].data
                  let y = null

                  // 优化逻辑 => 从两个循环变成了一个循环寻找对应x的y值
                  for (let index = 0; index < lineData.length; index += 2) {
                    if (index !== lineData.length - 1) {
                      if (x >= lineData[index] && x <= lineData[index + 2]) {
                        y = lineData[index + 1]
                        break
                      }
                    } else {
                      if (x <= lineData[index] && x >= lineData[index - 2]) {
                        y = lineData[index + 1]
                        break
                      }
                    }
                  }
                  if (isNaN(y)) y = null
                  return y
                  */
                  const temIndex = index || 0
                  const lineData = _Series[0].lines[temIndex].data
                  let y = null
                  let index1
                  // console.log('lineData[0]', lineData[0])
                  // 计算索引 => 更新了算法，占的比例不应该是点数的，而应该是间隔数的
                  if (lineData.length && lineData.length > 0) {
                    const index = Number(
                      (
                        ((x - lineData[0]) /
                          (lineData[lineData.length - 2] - lineData[0])) *
                        (lineData.length / 2 - 1)
                      ).toFixed(0)
                    )
                    index1 = index
                    y = lineData[2 * index + 1]
                  }
                  if (isNaN(y)) y = null
                  // console.log('悬停值', x, y, lineData)

                  return y
                },
                getIndex (x, index) {
                  const temIndex = index || 0
                  const lineData = _Series[0].lines[temIndex].data
                  let index1
                  // console.log('lineData[0]', lineData[0])
                  // 计算索引 => 更新了算法，占的比例不应该是点数的，而应该是间隔数的
                  if (lineData.length && lineData.length > 0) {
                    const index = Number(
                      (
                        ((x - lineData[0]) /
                                (lineData[lineData.length - 2] - lineData[0])) *
                              (lineData.length / 2 - 1)
                      ).toFixed(0)
                    )
                    index1 = index
                  }
                  return index1
                }
              }
            },
            addTooltip (tooltip) {
              newSeries.tooltip = tooltip
            },
            setMaxXInterval (newInterval) {
              newSeries.xAxis.interval = newInterval
              newSeries.xAxis.oldInterval = [newInterval[0], newInterval[1]]
              _clearCaculatedData()
              // 清空
              if (newSeries.kdCollection) {
                // newSeries.kdCollection.points = []
                newSeries.kdCollection = null
              }
            },
            setMaxXIntervalOnly (newInterval) {
              // newSeries.xAxis.interval = newInterval
              // //console.log(newInterval)
              newSeries.xAxis.oldInterval = [newInterval[0], newInterval[1]]
              if (
                newSeries.xAxis.interval[0] < newInterval[0] ||
                newSeries.xAxis.interval[1] > newInterval[1]
              ) {
                newSeries.xAxis.interval = newInterval
              }
              _clearCaculatedData()
            },
            changeXInterval (newInterval) {
              newSeries.xAxis.interval = newInterval
              _clearCaculatedData()
            },
            setMaxYInterval (newInterval) {
              newSeries.yAxis.interval = newInterval
              newSeries.yAxis.oldInterval = [newInterval[0], newInterval[1]]
              _clearCaculatedData()
            },
            setXAxisMarkFormatter (newXAxisMarkFormatter) {
              newSeries.xAxis.xAxisMarkFormatter = newXAxisMarkFormatter
              _clearCaculatedData()
            },
            getXInterval () {
              return [newSeries.xAxis.interval[0], newSeries.xAxis.interval[1]]
            },
            getMaxXInterval () {
              return [
                newSeries.xAxis.oldInterval[0],
                newSeries.xAxis.oldInterval[1]
              ]
            },
            changeYInterval (newInterval) {
              newSeries.yAxis.interval = newInterval
              _clearCaculatedData()
            },
            // 重置y轴为初始值
            resumeYInterval () {
              newSeries.yAxis.interval = [
                newSeries.yAxis.oldInterval[0],
                newSeries.yAxis.oldInterval[1]
              ]
              _clearCaculatedData()
            },
            getYInterval () {
              return [newSeries.yAxis.interval[0], newSeries.yAxis.interval[1]]
            },
            setOnXIntervalChange (onXIntervalChange) {
              newSeries.xAxis.onXIntervalChange = onXIntervalChange
            },
            addYMarkLine (yValue, color) {
              const markLine = {
                id: new Date().getTime() + ',' + _markIdIdx++,
                value: yValue,
                pixes: -9999999999,
                points: [],
                type: 'y',
                color: {
                  r: color ? color.r : 1,
                  g: color ? color.g : 1,
                  b: color ? color.b : 1
                }
              }
              newSeries.yAxis.markLines.push(markLine)
              return {
                setOnValueChangeListener (listener) {
                  markLine.onValueChangeListener = listener
                },
                /**
                 * 从series中删除当前markline
                 */
                remove () {
                  for (let i = 0; i < newSeries.xAxis.markLines.length; i++) {
                    const target = newSeries.xAxis.markLines[i]
                    if (target.id === markLine.id) {
                      newSeries.xAxis.markLines.splice(i, 1)
                      return
                    }
                  }
                  for (let i = 0; i < newSeries.yAxis.markLines.length; i++) {
                    const target = newSeries.yAxis.markLines[i]
                    if (target.id === markLine.id) {
                      newSeries.yAxis.markLines.splice(i, 1)
                      return
                    }
                  }
                }
              }
            },
            addXMarkLine (xValue, color) {
              const markLine = {
                id: new Date().getTime() + ',' + _markIdIdx++,
                visible: true,
                value: xValue,
                pixes: -9999999999,
                points: [],
                type: 'x',
                color: {
                  r: color ? color.r : 1,
                  g: color ? color.g : 1,
                  b: color ? color.b : 1
                }
              }
              newSeries.xAxis.markLines.push(markLine)
              return {
                setOnValueChangeListener (listener) {
                  markLine.onValueChangeListener = listener
                },
                setOnMouseUpListener (listener) {
                  markLine.onMouseUpListener = listener
                },
                /**
                 * 从series中删除当前markline
                 */
                remove () {
                  for (let i = 0; i < newSeries.xAxis.markLines.length; i++) {
                    const target = newSeries.xAxis.markLines[i]
                    if (target.id === markLine.id) {
                      newSeries.xAxis.markLines.splice(i, 1)
                      return
                    }
                  }
                  for (let i = 0; i < newSeries.yAxis.markLines.length; i++) {
                    const target = newSeries.yAxis.markLines[i]
                    if (target.id === markLine.id) {
                      newSeries.yAxis.markLines.splice(i, 1)
                      return
                    }
                  }
                },
                setVisible (visible) {
                  markLine.visible = visible
                },
                setValue (value) {
                  markLine.value = value
                  markLine.points = []
                }
              }
            },
            setOnClickListener (listener) {
              newSeries.onclickListener = listener
            },
            setOnMouseMoveListener (listener) {
              newSeries.onMouseMoveListener = listener
            },
            setOnMeasureListener (listener) {
              newSeries.onMeasureListener = listener
            },
            setShowMarkZoneWord (showMarkZoneWord) {
              newSeries.xAxis.showMarkZoneWord = showMarkZoneWord
            },
            /**
             * 添加mark
             * @param {*} start
             * @param {*} end
             * @param {*} str
             * @param {*} color
             */
            addXMarkZone (start, end, str, color) {
              newSeries.xAxis.markZones.push({
                start: start,
                end: end,
                points: [],
                str: str,
                color: color
              })
            },
            /**
             * 添加选中状态的mark （就是有白色左右边框）
             * @param {*} start
             * @param {*} end
             * @param {*} str
             * @param {*} color
             * @param {*} type
             */
            addXMarkZoneFocus (start, end, str, color) {
              newSeries.xAxis.markZones.push({
                start: start,
                end: end,
                points: [],
                str: str,
                color: color,
                borderColor: {
                  r: 255 / 255,
                  g: 255 / 255,
                  b: 255 / 255,
                  a: 1
                }
              })
            },
            addXMarkZoneHighLight (start, end, str) {
              newSeries.xAxis.markZonesHighLight.push({
                start: start,
                end: end,
                points: [],
                str: str
              })
            },
            /**
             * 添加黑名单的mark
             * @param {*} start
             * @param {*} end
             * @param {*} str
             */
            addXMarkZoneOfBlackList (start, end, str, color) {
              newSeries.xAxis.markZonesOfBlackList.push({
                start: start,
                end: end,
                points: [],
                str: str,
                color: color
              })
            },
            /**
             * 清空所有mark
             */
            clearXmarkZone () {
              newSeries.xAxis.markZones = []
              newSeries.xAxis.markZonePoints = []
              newSeries.xAxis.markZonePointColors = []
              newSeries.xAxis.markZoneLRPoints = []
              newSeries.xAxis.markZoneLRPointsColors = []
            },
            clearXmarkZoneOfBlackList () {
              newSeries.xAxis.markZonesOfBlackList = []
              newSeries.xAxis.markZonesOfBlackListPoints = []
              newSeries.xAxis.markZonesOfBlackListPointColors = []
              newSeries.xAxis.markZonesOfBlackListLRPoints = []
              newSeries.xAxis.markZonesOfBlackListLRPointsColors = []
            },
            clearXmarkZoneHighLight () {
              newSeries.xAxis.markZonesHighLight = []
            },
            changeDrageType (type) {
              if (type === 'zoom' || type === 'measure') {
                newSeries.dragType = type
              }
            },
            setSNRMeasureOpen (SNRMeasureOpen) {
              newSeries.SNRMeasureOpen = SNRMeasureOpen
            },
            setFreqMeasureOpen (freqMeasureOpen) {
              newSeries.freqMeasureOpen = freqMeasureOpen
            },
            setKdCollection (kdCollectionOpen, kdCollectionWidth) {
              newSeries.kdCollection = null
              newSeries.kdCollectionOpen = kdCollectionOpen
              newSeries.kdCollectionWidth = kdCollectionWidth
              _refresh()
            },
            setKdCollectionListener (kdCollectionListener) {
              newSeries.kdCollectionListener = kdCollectionListener
            },
            getKdCollectionValue () {
              return newSeries.kdCollection
                ? newSeries.kdCollection.kdCollectionPositionValue
                : null
            },
            setMouseClickPosition (x, y) {
              const series = _Series[0]
              const yPixes = _getYPixesByYvalue(y, series)
              const xPixes = _getXPixesByXvalue(x, series)
              const mouseClickMarkPoints = [
                series.yAxis.padding,
                yPixes,
                _container.clientWidth - series.yAxis.defaltPadding,
                yPixes,
                xPixes,
                series.xAxis.padding,
                xPixes,
                _container.clientHeight - series.xAxis.defaltPadding
              ]
              series.mouseClickMarkPoints = mouseClickMarkPoints

              _refresh()
            },
            setOnYIntervalChange (onYIntervalChange) {
              newSeries.yAxis.onYIntervalChange = onYIntervalChange
            },
            setAllowZoom (allowZoom) {
              newSeries.allowZoom = allowZoom
            }
          }
        },
        /**
         * 刷新当前图表
         */
        refresh () {
          _refresh()
        },
        reSize () {
          const div = document.querySelector('#' + _config.container)
          _container.width = div.clientWidth
          _container.height = div.clientHeight
          _textcontainer.width = div.clientWidth
          _textcontainer.height = div.clientHeight
          _textCtx.width = div.clientWidth
          _textCtx.height = div.clientHeight
          _clearCaculatedData()
          // 清空计算矩阵
          _axisMatrix = null
          _Series.forEach((series) => {
            series._linesMatrix = null
            // 清空axis标记  的文字缓存
            series.xAxis.points = []
            series.yAxis.points = []
          })
          _refresh()
        }
      }
    }
  }
}

export default Chart
